home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / RENDER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-21  |  93.3 KB  |  3,972 lines

  1. /****************************************************************************
  2. *                   render.c
  3. *
  4. *  This module implements the main raytracing loop.
  5. *
  6. * 08/07/92 lsk    Changed the normal antialiasing function to use a loop 
  7. *                 where the number of rays per pixel when antialiasing can 
  8. *                 be specified.
  9. *
  10. *  from Persistence of Vision(tm) Ray Tracer
  11. *  Copyright 1996 Persistence of Vision Team
  12. *---------------------------------------------------------------------------
  13. *  NOTICE: This source code file is provided so that users may experiment
  14. *  with enhancements to POV-Ray and to port the software to platforms other
  15. *  than those supported by the POV-Ray Team.  There are strict rules under
  16. *  which you are permitted to use this file.  The rules are in the file
  17. *  named POVLEGAL.DOC which should be distributed with this file. If
  18. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  19. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  20. *  Forum.  The latest version of POV-Ray may be found there as well.
  21. *
  22. * This program is based on the popular DKB raytracer version 2.12.
  23. * DKBTrace was originally written by David K. Buck.
  24. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  25. *
  26. ******************************************************************************/
  27.  
  28. #include <time.h>
  29. #include "frame.h"
  30. #include "vector.h"
  31. #include "povproto.h"
  32. #include "bbox.h"
  33. #include "chi2.h"
  34. #include "colour.h"
  35. #include "lighting.h"
  36. #include "normal.h"
  37. #include "objects.h"
  38. #include "octree.h"
  39. #include "optout.h"
  40. #include "povray.h"
  41. #include "radiosit.h"
  42. #include "ray.h"
  43. #include "render.h"
  44. #include "targa.h"
  45. #include "texture.h"
  46. #include "vbuffer.h"
  47. #include "userio.h"
  48.  
  49.  
  50. /*****************************************************************************
  51. * Local preprocessor defines
  52. ******************************************************************************/
  53.  
  54. #define rand2d(a, b) jitttab[(int)(hashTable[(int)(hashTable[(int)((a)&0xfff)]^(b))&0xfff])&0xff]
  55.  
  56. /* Grid stuff used by focal blur code. */
  57.  
  58. #define grid1size  4
  59. #define hexgrid2size  7
  60. #define hexgrid3size  19
  61. #define hexgrid4size  37
  62.  
  63. /* Grid size (n x n) used while jittering focal blur sub-pixel position. */
  64.  
  65. #define SUB_PIXEL_GRID_SIZE 16
  66.  
  67. /*****************************************************************************
  68. * Local typedefs
  69. ******************************************************************************/
  70.  
  71. typedef struct Pixel_Struct PIXEL;
  72. typedef struct Vec2_Struct VEC2;
  73.  
  74. struct Vec2_Struct
  75. {
  76.   DBL x, y;
  77. };
  78.  
  79. struct Pixel_Struct
  80. {
  81.   int active;
  82.   COLOUR Colour;
  83. };
  84.  
  85.  
  86.  
  87. /*****************************************************************************
  88. * Local variables
  89. ******************************************************************************/
  90.  
  91. int Trace_Level;
  92. int Max_Trace_Level = 5;
  93. int Highest_Trace_Level; /* DMF */
  94.  
  95. /* ADC stuff by DMF. */
  96.  
  97. DBL ADC_Bailout = 1.0/255.0;
  98.  
  99. static COLOUR *Previous_Line, *Current_Line;
  100. static char *Previous_Line_Antialiased_Flags, *Current_Line_Antialiased_Flags;
  101.  
  102. static RAY Camera_Ray;
  103.  
  104. static int SuperSampleCount, RadiosityCount;
  105.  
  106. static DBL maxclr;
  107.  
  108. /* Jitter values are taken from [-0.5*JitterScale, 0.5*JitterScale]. */
  109.  
  110. static DBL JitterScale;
  111.  
  112. /* Jitter ranges unsed during supersampling. */
  113.  
  114. static unsigned short JRanges[] = {1,1,1,1,3,2,5,3,7,4};
  115.  
  116. /* variables used by accumulate_histogram() for statistics on the render */
  117.  
  118. unsigned long           *histogram_grid;
  119. unsigned long           max_histogram_value;
  120. FILE_HANDLE             *Histogram_File_Handle;
  121.  
  122. /*
  123.  * Focal blur stuff.
  124.  */
  125.  
  126. /* Flag telling if focal blur is used. */
  127.  
  128. static int Focal_Blur_Is_Used;
  129.  
  130. /* Direction to focal plane. */
  131.  
  132. static DBL Focal_Distance;
  133.  
  134. /* Array of threshold for confidence test. */
  135.  
  136. static DBL *Sample_Threshold;
  137.  
  138. /* Array giving number of samples to take before next confidence test. */
  139.  
  140. static int *Current_Number_Of_Samples;
  141.  
  142. /* Array of sample locations. */
  143.  
  144. static VEC2 *Sample_Grid;
  145.  
  146. /* Maximum amount of jitter to use. */
  147.  
  148. static DBL Max_Jitter;
  149.  
  150. /* Vectors in the viewing plane. */
  151.  
  152. static VECTOR XPerp, YPerp;
  153.  
  154. /* 2*2 grid */
  155.  
  156. static VEC2 grid1[grid1size] =
  157. {
  158.   {-0.25,  0.25},
  159.   { 0.25,  0.25},
  160.   {-0.25, -0.25},
  161.   { 0.25, -0.25}
  162. };
  163.  
  164. static DBL hexjitter2 = 0.144338;
  165. static int hexgrid2samples[2] = { 7, 0 };
  166. static VEC2 hexgrid2 [hexgrid2size] =
  167. {
  168.   {-0.288675,  0.000000},
  169.   { 0.000000,  0.000000},
  170.   { 0.288675,  0.000000},
  171.   {-0.144338,  0.250000},
  172.   {-0.144338, -0.250000},
  173.   { 0.144338,  0.250000},
  174.   { 0.144338, -0.250000}
  175. };
  176.  
  177. static DBL hexjitter3 = 0.096225;
  178. static int hexgrid3samples[4] = { 7, 6, 6, 0 };
  179. static VEC2 hexgrid3 [hexgrid3size] =
  180. {
  181.   {-0.192450,  0.333333},
  182.   {-0.192450, -0.333333},
  183.   { 0.192450,  0.333333},
  184.   { 0.192450, -0.333333},
  185.   { 0.384900,  0.000000},
  186.   {-0.384900,  0.000000},
  187.   { 0.000000,  0.000000},
  188.  
  189.   { 0.000000,  0.333333},
  190.   { 0.000000, -0.333333},
  191.   {-0.288675,  0.166667},
  192.   {-0.288675, -0.166667},
  193.   { 0.288675,  0.166667},
  194.   { 0.288675, -0.166667},
  195.  
  196.   {-0.096225,  0.166667},
  197.   {-0.096225, -0.166667},
  198.   { 0.096225,  0.166667},
  199.   { 0.096225, -0.166667},
  200.   {-0.192450,  0.000000},
  201.   { 0.192450,  0.000000}
  202. };
  203.  
  204. static DBL hexjitter4 = 0.0721688;
  205. static int hexgrid4samples[9] = { 7, 6, 6, 4, 4, 4, 4, 2, 0 };
  206. static VEC2 hexgrid4 [hexgrid4size] =
  207. {
  208.   { 0.000000,  0.000000},
  209.   {-0.216506,  0.375000},
  210.   { 0.216506, -0.375000},
  211.   {-0.216506, -0.375000},
  212.   { 0.216506,  0.375000},
  213.   {-0.433013,  0.000000},
  214.   { 0.433013,  0.000000},
  215.  
  216.   {-0.144338,  0.250000},
  217.   { 0.144338, -0.250000},
  218.   {-0.144338, -0.250000},
  219.   { 0.144338,  0.250000},
  220.   {-0.288675,  0.000000},
  221.   { 0.288675,  0.000000},
  222.  
  223.   {-0.072169,  0.125000},
  224.   { 0.072169, -0.125000},
  225.   {-0.072169, -0.125000},
  226.   { 0.072169,  0.125000},
  227.   {-0.144338,  0.000000},
  228.   { 0.144338,  0.000000},
  229.  
  230.   {-0.360844,  0.125000},
  231.   {-0.360844, -0.125000},
  232.   { 0.360844,  0.125000},
  233.   { 0.360844, -0.125000},
  234.  
  235.   {-0.288675,  0.250000},
  236.   {-0.288675, -0.250000},
  237.   { 0.288675,  0.250000},
  238.   { 0.288675, -0.250000},
  239.  
  240.   {-0.072169,  0.375000},
  241.   {-0.072169, -0.375000},
  242.   { 0.072169,  0.375000},
  243.   { 0.072169, -0.375000},
  244.  
  245.   {-0.216506,  0.125000},
  246.   {-0.216506, -0.125000},
  247.   { 0.216506,  0.125000},
  248.   { 0.216506, -0.125000},
  249.  
  250.   { 0.000000,  0.250000},
  251.   { 0.000000, -0.250000},
  252. };
  253.  
  254. static float jitttab[256] = {
  255.   -0.500000,0.005890,0.011749,-0.490234,0.023468,-0.470703,-0.480469,0.017609,
  256.   0.046906,-0.447266,-0.441406,0.056671,-0.460938,0.044952,0.035187,-0.466797,
  257.   0.093781,-0.400391,-0.394531,0.103546,-0.382813,0.123077,0.113312,-0.388672,
  258.   -0.421875,0.084015,0.089874,-0.412109,0.070343,-0.423828,-0.433594,0.064484,
  259.   0.187531,-0.306641,-0.300781,0.197296,-0.289063,0.216827,0.207062,-0.294922,
  260.   -0.265625,0.240265,0.246124,-0.255859,0.226593,-0.267578,-0.277344,0.220734,
  261.   -0.343750,0.162140,0.167999,-0.333984,0.179718,-0.314453,-0.324219,0.173859,
  262.   0.140656,-0.353516,-0.347656,0.150421,-0.367188,0.138702,0.128937,-0.373047,
  263.   0.375031,-0.119141,-0.113281,0.384796,-0.101563,0.404327,0.394562,-0.107422,
  264.   -0.078125,0.427765,0.433624,-0.068359,0.414093,-0.080078,-0.089844,0.408234,
  265.   -0.031250,0.474640,0.480499,-0.021484,0.492218,-0.001953,-0.011719,0.486359,
  266.   0.453156,-0.041016,-0.035156,0.462921,-0.054688,0.451202,0.441437,-0.060547,
  267.   -0.187500,0.318390,0.324249,-0.177734,0.335968,-0.158203,-0.167969,0.330109,
  268.   0.359406,-0.134766,-0.128906,0.369171,-0.148438,0.357452,0.347687,-0.154297,
  269.   0.281281,-0.212891,-0.207031,0.291046,-0.195313,0.310577,0.300812,-0.201172,
  270.   -0.234375,0.271515,0.277374,-0.224609,0.257843,-0.236328,-0.246094,0.251984,
  271.   -0.249969,0.255859,0.261719,-0.240204,0.273438,-0.220673,-0.230438,0.267578,
  272.   0.296875,-0.197235,-0.191376,0.306641,-0.210907,0.294922,0.285156,-0.216766,
  273.   0.343750,-0.150360,-0.144501,0.353516,-0.132782,0.373047,0.363281,-0.138641,
  274.   -0.171844,0.333984,0.339844,-0.162079,0.320313,-0.173798,-0.183563,0.314453,
  275.   0.437500,-0.056610,-0.050751,0.447266,-0.039032,0.466797,0.457031,-0.044891,
  276.   -0.015594,0.490234,0.496094,-0.005829,0.476563,-0.017548,-0.027313,0.470703,
  277.   -0.093719,0.412109,0.417969,-0.083954,0.429688,-0.064423,-0.074188,0.423828,
  278.   0.390625,-0.103485,-0.097626,0.400391,-0.117157,0.388672,0.378906,-0.123016,
  279.   0.125000,-0.369110,-0.363251,0.134766,-0.351532,0.154297,0.144531,-0.357391,
  280.   -0.328094,0.177734,0.183594,-0.318329,0.164063,-0.330048,-0.339813,0.158203,
  281.   -0.281219,0.224609,0.230469,-0.271454,0.242188,-0.251923,-0.261688,0.236328,
  282.   0.203125,-0.290985,-0.285126,0.212891,-0.304657,0.201172,0.191406,-0.310516,
  283.   -0.437469,0.068359,0.074219,-0.427704,0.085938,-0.408173,-0.417938,0.080078,
  284.   0.109375,-0.384735,-0.378876,0.119141,-0.398407,0.107422,0.097656,-0.404266,
  285.   0.031250,-0.462860,-0.457001,0.041016,-0.445282,0.060547,0.050781,-0.451141,
  286.   -0.484344,0.021484,0.027344,-0.474579,0.007813,-0.486298,-0.496063,0.001953,
  287. };
  288.  
  289. /* Precomputed ray container values. */
  290.  
  291. static int Primary_Ray_State_Tested;
  292. static int Containing_Index;
  293. static TEXTURE *Containing_Textures[MAX_CONTAINING_OBJECTS];
  294. static OBJECT  *Containing_Objects[MAX_CONTAINING_OBJECTS];
  295. static DBL      Containing_IORs[MAX_CONTAINING_OBJECTS];
  296.  
  297. /* Flag wether to compute camera constant that don't change during one frame. */
  298.  
  299. static int Precompute_Camera_Constants;
  300. static DBL Camera_Aspect_Ratio;
  301.  
  302.  
  303.  
  304.  
  305.  
  306. /*****************************************************************************
  307. * Local functions
  308. ******************************************************************************/
  309.  
  310. static void focal_blur PARAMS((RAY *Ray, COLOUR Colour, DBL x, DBL y));
  311. static void jitter_camera_ray PARAMS((RAY *ray, int ray_number));
  312. static void check_stats PARAMS((int y, int doingMosaic, int pixWidth));
  313. static void do_anti_aliasing PARAMS((int x, int y, COLOUR Colour));
  314. static void output_line PARAMS((int y));
  315. static int  create_ray PARAMS((RAY *ray, DBL x, DBL y, int ray_number));
  316. static void supersample PARAMS((COLOUR result, int x, int y));
  317. static void gamma_correct PARAMS((COLOUR Colour));
  318. static void extract_colors PARAMS((COLOUR Colour, unsigned char *Red, unsigned char *Green, unsigned char *Blue, unsigned char *Alpha, DBL *grey));
  319. static void trace_pixel PARAMS((int x, int y, COLOUR Colour));
  320. static void initialise_histogram PARAMS((void)) ;
  321. static void accumulate_histogram PARAMS((int x, int y, int on));
  322. static void plot_pixel PARAMS((int x, int y, COLOUR Colour));
  323. static void jitter_pixel_position PARAMS((int x, int y, DBL *Jitter_X, DBL *Jitter_Y));
  324. static void trace_sub_pixel PARAMS((int level, PIXEL **Block, int x, int y, int x1, int y1, int x2, int y2, int size, COLOUR Colour, int antialias));
  325. static void trace_ray_with_offset PARAMS((int x, int y, DBL dx, DBL dy, COLOUR Colour));
  326. static void initialize_ray_container_state PARAMS((RAY *Ray, int Compute));
  327. static void initialize_ray_container_state_tree PARAMS((RAY *Ray, BBOX_TREE *Node));
  328.  
  329.  
  330.  
  331. /*****************************************************************************
  332. *
  333. * FUNCTION
  334. *
  335. *   Initialize_Renderer
  336. *
  337. * INPUT
  338. *   
  339. * OUTPUT
  340. *   
  341. * RETURNS
  342. *   
  343. * AUTHOR
  344. *
  345. *   POV-Ray Team
  346. *   
  347. * DESCRIPTION
  348. *
  349. *   Setup renderer. Allocate memory for line storage.
  350. *
  351. * CHANGES
  352. *
  353. *   -
  354. *
  355. ******************************************************************************/
  356.  
  357. void Initialize_Renderer PARAMS((void))
  358. {
  359.   char **Grid;
  360.   int i, xi, yi, Grid_Size;
  361.   int Standard_Sample_Grid_Size;
  362.   size_t size;
  363.   DBL x, y, len;
  364.   DBL T1;
  365.   VEC2 *Standard_Sample_Grid;
  366.  
  367.   maxclr = (DBL)(1 << Color_Bits) - 1.0;
  368.  
  369.   size = (Frame.Screen_Width + 1) * sizeof(COLOUR);
  370.  
  371.   Previous_Line = (COLOUR *)POV_MALLOC(size, "previous line buffer");
  372.   Current_Line  = (COLOUR *)POV_MALLOC(size, "current line buffer");
  373.  
  374.   for (i = 0; i <= Frame.Screen_Width ; i++)
  375.   {
  376.     Make_ColourA(Previous_Line[i], 0.0, 0.0, 0.0, 0.0, 0.0);
  377.     Make_ColourA(Current_Line[i],  0.0, 0.0, 0.0, 0.0, 0.0);
  378.   }
  379.  
  380.   if (opts.Options & ANTIALIAS)
  381.   {
  382.     size = (Frame.Screen_Width + 1) * sizeof(char);
  383.  
  384.     Previous_Line_Antialiased_Flags = (char *)POV_MALLOC(size, "previous line flags");
  385.     Current_Line_Antialiased_Flags  = (char *)POV_MALLOC(size, "current line flags");
  386.  
  387.     for (i = 0; i <= Frame.Screen_Width ; i++)
  388.     {
  389.       Previous_Line_Antialiased_Flags[i] = 0;
  390.       Current_Line_Antialiased_Flags[i]  = 0;
  391.     }
  392.   }
  393.  
  394.   Assign_Vector(Camera_Ray.Initial, Frame.Camera->Location);
  395.  
  396.   if (opts.histogram_on)
  397.   {
  398.     initialise_histogram();
  399.   }
  400.  
  401.   Focal_Blur_Is_Used = (Frame.Camera->Aperture != 0.0) && (Frame.Camera->Blur_Samples > 0);
  402.  
  403.   /* Init focal blur stuff. */
  404.  
  405.   Sample_Grid = NULL;
  406.  
  407.   Sample_Threshold = NULL;
  408.  
  409.   if (Focal_Blur_Is_Used)
  410.   {
  411.     /* Create list of thresholds for confidence test. */
  412.  
  413.     Sample_Threshold = (DBL *)POV_MALLOC(Frame.Camera->Blur_Samples*sizeof(DBL), "sample threshold list");
  414.  
  415.     if (Frame.Camera->Blur_Samples > 1)
  416.     {
  417.       T1 = Frame.Camera->Variance / chdtri((DBL)(Frame.Camera->Blur_Samples-1), Frame.Camera->Confidence);
  418.  
  419.       for (i = 0; i < Frame.Camera->Blur_Samples; i++)
  420.       {
  421.         Sample_Threshold[i] = T1 * chdtri((DBL)(i+1), Frame.Camera->Confidence);
  422.       }
  423.     }
  424.     else
  425.     {
  426.       Sample_Threshold[0] = 0.0;
  427.     }
  428.  
  429.     /* Create list of sample positions. */
  430.  
  431.     Sample_Grid = (VEC2 *)POV_MALLOC(Frame.Camera->Blur_Samples*sizeof(VEC2), "sample grid");
  432.  
  433.     /*
  434.      * Choose sample list and the best standard grid to use.
  435.      */
  436.  
  437.     /* Default is 4x4 standard grid. */
  438.  
  439.     Standard_Sample_Grid = &grid1[0];
  440.  
  441.     Standard_Sample_Grid_Size = 4;
  442.  
  443.     Current_Number_Of_Samples = NULL;
  444.  
  445.     /* Check for 7 samples hexgrid. */
  446.  
  447.     if (Frame.Camera->Blur_Samples >= hexgrid2size)
  448.     {
  449.       Standard_Sample_Grid = &hexgrid2[0];
  450.  
  451.       Standard_Sample_Grid_Size = hexgrid2size;
  452.  
  453.       Current_Number_Of_Samples = &hexgrid2samples[0];
  454.     }
  455.  
  456.     /* Check for 19 samples hexgrid. */
  457.  
  458.     if (Frame.Camera->Blur_Samples >= hexgrid3size)
  459.     {
  460.       Standard_Sample_Grid = &hexgrid3[0];
  461.  
  462.       Standard_Sample_Grid_Size = hexgrid3size;
  463.  
  464.       Current_Number_Of_Samples = &hexgrid3samples[0];
  465.     }
  466.  
  467.     /* Check for 37 samples hexgrid. */
  468.  
  469.     if (Frame.Camera->Blur_Samples >= hexgrid4size)
  470.     {
  471.       Standard_Sample_Grid = &hexgrid4[0];
  472.  
  473.       Standard_Sample_Grid_Size = hexgrid4size;
  474.  
  475.       Current_Number_Of_Samples = &hexgrid4samples[0];
  476.     }
  477.  
  478.     /* Get max. jitter. */
  479.  
  480.     switch (Frame.Camera->Blur_Samples)
  481.     {
  482.       case hexgrid2size :
  483.  
  484.         Max_Jitter = hexjitter2;
  485.  
  486.         break;
  487.  
  488.       case hexgrid3size :
  489.  
  490.         Max_Jitter = hexjitter3;
  491.  
  492.         break;
  493.  
  494.       case hexgrid4size :
  495.  
  496.         Max_Jitter = hexjitter4;
  497.  
  498.         break;
  499.  
  500.       default:
  501.  
  502.         Max_Jitter = 1.0 / (2.0 * sqrt((DBL)Frame.Camera->Blur_Samples));
  503.     }
  504.  
  505.     /* Copy standard grid to sample grid. */
  506.  
  507.     for (i = 0; i < min(Standard_Sample_Grid_Size, Frame.Camera->Blur_Samples); i++)
  508.     {
  509.       Sample_Grid[i] = Standard_Sample_Grid[i];
  510.     }
  511.  
  512.     /* Choose remaining samples from a uniform grid to get "best" coverage. */
  513.  
  514.     if (Frame.Camera->Blur_Samples > Standard_Sample_Grid_Size)
  515.     {
  516.       /* Get sub-pixel grid size (I want it to be odd). */
  517.  
  518.       Grid_Size = (int)sqrt((DBL)Frame.Camera->Blur_Samples) + 1;
  519.  
  520.       if ((Grid_Size & 1) == 0)
  521.       {
  522.         Grid_Size++;
  523.       }
  524.  
  525.       /* Allocate temporary grid. */
  526.  
  527.       Grid = (char **)POV_MALLOC(Grid_Size * sizeof(int *), "temporary sub-pixel grid");
  528.  
  529.       for (i = 0; i < Grid_Size; i++)
  530.       {
  531.         Grid[i] = (char *)POV_CALLOC((unsigned)Grid_Size, sizeof(int), "temporary sub-pixel grid");
  532.       }
  533.  
  534.       /* Mark sub-pixels already covered. */
  535.  
  536.       for (i = 0; i < Standard_Sample_Grid_Size; i++)
  537.       {
  538.         xi = (int)((Sample_Grid[i].x + 0.5) * (DBL)Grid_Size);
  539.         yi = (int)((Sample_Grid[i].y + 0.5) * (DBL)Grid_Size);
  540.  
  541.         Grid[yi][xi] = TRUE;
  542.       }
  543.  
  544.       /* Distribute remaining samples. */
  545.  
  546.       for (i = Standard_Sample_Grid_Size; i < Frame.Camera->Blur_Samples; )
  547.       {
  548.         xi = POV_RAND() % Grid_Size;
  549.         yi = POV_RAND() % Grid_Size;
  550.  
  551.         if (!Grid[yi][xi])
  552.         {
  553.           x = (DBL)(2 * xi + 1) / (DBL)(2 * Grid_Size) - 0.5;
  554.           y = (DBL)(2 * yi + 1) / (DBL)(2 * Grid_Size) - 0.5;
  555.  
  556.           Sample_Grid[i].x = x;
  557.           Sample_Grid[i].y = y;
  558.  
  559.           Grid[yi][xi] = TRUE;
  560.  
  561.           i++;
  562.         }
  563.       }
  564.  
  565.       /* Free temporary grid. */
  566.  
  567.       for (i = 0; i < Grid_Size; i++)
  568.       {
  569.         POV_FREE(Grid[i]);
  570.       }
  571.  
  572.       POV_FREE(Grid);
  573.     }
  574.  
  575.     /*
  576.      * Calculate vectors perpendicular to the current ray
  577.      * We're making a "+" (crosshair) on the film plane.
  578.      */
  579.  
  580.     /* XPerp = vector perpendicular to y/z plane */
  581.  
  582.     VCross(XPerp, Frame.Camera->Up, Frame.Camera->Direction);
  583.  
  584.     VNormalize(XPerp, XPerp);
  585.  
  586.     /* YPerp = vector perpendicular to x/z plane */
  587.  
  588.     VCross(YPerp, Frame.Camera->Direction, XPerp);
  589.  
  590.     VNormalize(YPerp, YPerp);
  591.  
  592.     /* Get adjusted distance to focal plane. */
  593.  
  594.     VLength(len, Frame.Camera->Direction);
  595.  
  596.     Focal_Distance = Frame.Camera->Focal_Distance / len;
  597.   }
  598.  
  599.   /* If a single frame is traced disable field rendering. */
  600. /* Disabled 11/12/95 CEY
  601.   if (opts.FrameSeq.FrameType == FT_SINGLE_FRAME)
  602.   {
  603.     opts.FrameSeq.Field_Render_Flag = FALSE;
  604.   }
  605. */
  606.  
  607.   /* We have to precalculate all camera constants. */
  608.  
  609.   Precompute_Camera_Constants = TRUE;
  610.  
  611.   Primary_Ray_State_Tested = FALSE; 
  612. }
  613.  
  614.  
  615.  
  616. /*****************************************************************************
  617. *
  618. * FUNCTION
  619. *
  620. *   Terminate_Renderer
  621. *
  622. * INPUT
  623. *
  624. * OUTPUT
  625. *
  626. * RETURNS
  627. *
  628. * AUTHOR
  629. *
  630. *   POV-Ray Team
  631. *   
  632. * DESCRIPTION
  633. *
  634. *   -
  635. *
  636. * CHANGES
  637. *
  638. *   -
  639. *
  640. ******************************************************************************/
  641.  
  642. void Terminate_Renderer()
  643. {
  644.   if (Previous_Line != NULL)
  645.   {
  646.     POV_FREE(Previous_Line);
  647.     POV_FREE(Current_Line);
  648.  
  649.     Previous_Line = NULL;
  650.     Current_Line  = NULL;
  651.   }
  652.  
  653.   if (Previous_Line_Antialiased_Flags != NULL)
  654.   {
  655.     POV_FREE(Previous_Line_Antialiased_Flags);
  656.     POV_FREE(Current_Line_Antialiased_Flags);
  657.  
  658.     Previous_Line_Antialiased_Flags = NULL;
  659.     Current_Line_Antialiased_Flags  = NULL;
  660.   }
  661.  
  662.   if (Focal_Blur_Is_Used)
  663.   {
  664.     if (Sample_Threshold != NULL)
  665.     {
  666.       POV_FREE(Sample_Threshold);
  667.  
  668.       Sample_Threshold = NULL;
  669.     }
  670.  
  671.     if (Sample_Grid != NULL)
  672.     {
  673.       POV_FREE(Sample_Grid);
  674.  
  675.       Sample_Grid = NULL;
  676.     }
  677.   }
  678. }
  679.  
  680.  
  681.  
  682. /*****************************************************************************
  683. *
  684. * FUNCTION
  685. *
  686. *   Read_Rendered_Part
  687. *
  688. * INPUT
  689. *   
  690. * OUTPUT
  691. *   
  692. * RETURNS
  693. *   
  694. * AUTHOR
  695. *
  696. *   POV-Ray Team
  697. *   
  698. * DESCRIPTION
  699. *
  700. *   -
  701. *
  702. * CHANGES
  703. *
  704. *   Sep 1994 : Call extract_colors to get pixel's color. [DB]
  705. *
  706. ******************************************************************************/
  707.  
  708. void Read_Rendered_Part(New_Fname)
  709. char *New_Fname;
  710. {
  711.   int rc, x, line_number = 0;
  712.   unsigned char Red, Green, Blue, Alpha;
  713.   DBL grey;
  714.  
  715.   maxclr = (DBL)(1 << Color_Bits) - 1.0;
  716.  
  717.   while ((rc = Read_Line(Output_File_Handle, Previous_Line, &line_number)) == 1)
  718.   {
  719.     if (opts.Options & DISPLAY)
  720.     {
  721.       for (x = 0; x < Frame.Screen_Width ; x++)
  722.       {
  723.         extract_colors(Previous_Line[x], &Red, &Green, &Blue, &Alpha, &grey);
  724.  
  725.         POV_DISPLAY_PLOT(x, line_number, Red, Green, Blue, Alpha);
  726.  
  727.         COOPERATE_1
  728.       }
  729.     }
  730.   }
  731.  
  732.   opts.First_Line = line_number + 1;
  733.  
  734.   Close_File(Output_File_Handle);
  735.  
  736.   if (rc == 0)
  737.   {
  738.     if (Open_File(Output_File_Handle, New_Fname,
  739.         &Frame.Screen_Width, &Frame.Screen_Height, opts.File_Buffer_Size,
  740.         APPEND_MODE) != 1)
  741.     {
  742.       Error("Error opening output file.\n");
  743.     }
  744.  
  745.     return;
  746.   }
  747.  
  748.   Error("Error reading aborted data file.\n");
  749. }
  750.  
  751.  
  752.  
  753. /*****************************************************************************
  754. *
  755. * FUNCTION
  756. *
  757. *   Check_User_Abort
  758. *
  759. * INPUT
  760. *
  761. *   Forced -- if FALSE, then check else force user abort
  762. *   
  763. * OUTPUT
  764. *   
  765. * RETURNS
  766. *   
  767. * AUTHOR
  768. *
  769. *   POV-Ray Team
  770. *   
  771. * DESCRIPTION
  772. *
  773. *   Exit with error if image not completed/user abort.
  774. *
  775. * CHANGES
  776. *
  777. *   -
  778. *
  779. ******************************************************************************/
  780.  
  781. void Check_User_Abort(Forced)
  782. int Forced;
  783. {
  784.   if (Forced)
  785.   {
  786.      Stop_Flag=TRUE;
  787.   }
  788.   else
  789.   {
  790.     if (--opts.Abort_Test_Counter <= 0)
  791.     {
  792.       opts.Abort_Test_Counter = Abort_Test_Every;
  793.  
  794.       TEST_ABORT
  795.     }
  796.   }
  797.  
  798.   if (Stop_Flag)
  799.   {
  800.     Render_Info("\nAborting render...\n");
  801.  
  802. /*
  803.     if ((opts.Options & DISPLAY) && Display_Started)
  804.     {
  805.       POV_DISPLAY_CLOSE
  806.     }
  807. */
  808.  
  809.   if ((opts.Options & DISPLAY) && Display_Started)
  810.   {
  811.     POV_DISPLAY_CLOSE
  812.   }
  813.   else
  814.   {
  815.   if ((!(opts.Options & VERBOSE)) && Blanker_Started)
  816.   {
  817.     POV_DISPLAY_CLOSE
  818.   }
  819.   }
  820.  
  821.  
  822.  
  823.     if (opts.Do_Stats)
  824.     {
  825.       PRINT_STATS(stats);
  826.     }
  827.  
  828.     Error("User abort.\n");
  829.   }
  830. }
  831.  
  832.  
  833.  
  834. /*****************************************************************************
  835. *
  836. * FUNCTION
  837. *
  838. *   Start_Tracing_Mosaic_Preview
  839. *
  840. * INPUT
  841. *
  842. *   MosaicPixelSize - # of pixels square to start
  843. *   
  844. * OUTPUT
  845. *   
  846. * RETURNS
  847. *   
  848. * AUTHOR
  849. *
  850. *   Eduard Schwan
  851. *   
  852. * DESCRIPTION
  853. *
  854. *   Trace the entire image, but instead of doing it pixel by pixel,
  855. *   draw every 8th pixel, then every 4th, then every 2nd, then
  856. *   every pixel. This shows the image as a quick chunky preview,
  857. *   and the image gets more detailed as each pass redraws it in
  858. *   increasing detail.  This is a simple subdivision preview method.
  859. *   On the first pass, the entire screen is painted.  On each subsequent
  860. *   pass, smaller squares are painted to fill in more detail.  Any
  861. *   squares that were already calculated on previous passes are NOT
  862. *   redrawn, making this mode just as fast as the non-preview rendering
  863. *   mode (ignoring additional time used by rectangle screen painting.)
  864. *
  865. * CHANGES
  866. *
  867. *   Aug 1994 : Created from Start_Tracing, by Eduard Schwan
  868. *   Dec 1994 : Updated for more regular scanning, by Eduard Schwan
  869. *
  870. ******************************************************************************/
  871.  
  872. void Start_Tracing_Mosaic_Preview(StartPixelSize, EndPixelSize)
  873. int StartPixelSize, EndPixelSize;
  874. {
  875.   unsigned char Red, Green, Blue, Alpha;
  876.   int x, y, x2, y2, PreviewStep, PixelSize, AlreadyPainted, PreviewPass;
  877.   COLOUR Colour;
  878.   DBL grey;
  879.  
  880.   /* PreviewStep tracks how many pixels to skip on each square painted */
  881.  
  882.   PreviewStep = StartPixelSize;
  883.  
  884.   /* do each pass of the image */
  885.   /* increment pass counter and divide PixelSize & PreviewStep by 2 */
  886.  
  887.   for (PreviewPass = 1, PixelSize = StartPixelSize;
  888.         PixelSize >= EndPixelSize;
  889.         PreviewPass++, PixelSize >>= 1, PreviewStep >>= 1)
  890.   {
  891.     /* do each row */
  892.  
  893.     for (y = opts.First_Line; y < opts.Last_Line; y += PreviewStep)
  894.     {
  895.       /* show some status information */
  896.       /* note, this fn should change to show new style for preview */
  897.  
  898.       check_stats(y, 1, PixelSize);
  899.  
  900.       /* do each column/pixel on a row */
  901.  
  902.       for (x = opts.First_Column; x < opts.Last_Column; x += PreviewStep)
  903.       {
  904.         Check_User_Abort(FALSE);
  905.  
  906.         /*
  907.          * Skip any pixels we have done previously.  These would be any pixels
  908.          * that are on a row AND column that is divisible by the previous
  909.          * pass's step-size.  On the first pass, however, do ALL pixels, since
  910.          * there is nothing to skip.
  911.          */
  912.  
  913.         AlreadyPainted = FALSE;
  914.  
  915.         if (PreviewPass > 1)
  916.         {
  917.           if ( ((x-opts.First_Column) % (PreviewStep*2) == 0) &&
  918.                ((y-opts.First_Line) % (PreviewStep*2) == 0) )
  919.           {
  920.             AlreadyPainted = TRUE;
  921.           }
  922.         }
  923.  
  924.         if (!AlreadyPainted)
  925.         {
  926.           /* OK, it is safe to draw this pixel */
  927.  
  928.           trace_pixel(x, y, Colour);
  929.  
  930.           extract_colors(Colour, &Red, &Green, &Blue, &Alpha, &grey);
  931.  
  932.           y2 = min(y + PixelSize - 1, opts.Last_Line);
  933.           x2 = min(x + PixelSize - 1, opts.Last_Column);
  934.  
  935.           POV_DISPLAY_PLOT_RECT(x, x2, y, y2, Red, Green, Blue, Alpha);
  936.         }
  937.       }
  938.  
  939.       if (opts.Options & VERBOSE)
  940.       {
  941.         Status_Info("\r");
  942.       }
  943.     }
  944.   }
  945. }
  946.  
  947.  
  948.  
  949. /*****************************************************************************
  950. *
  951. * FUNCTION
  952. *
  953. *   Start_Tracing_Mosaic_Smooth
  954. *
  955. * INPUT
  956. *
  957. *   MosaicPixelSize - # of pixels square to start
  958. *   
  959. * OUTPUT
  960. *
  961. * RETURNS
  962. *   
  963. * AUTHOR
  964. *
  965. *   Eduard Schwan
  966. *   
  967. * DESCRIPTION
  968. *
  969. *   See comments for Start_Tracing_Mosaic_Preview.
  970. *   Radiosity requires this pass, so it is not optional, and does not
  971. *   require you to set Mosaic_Preview_Start and End.
  972. *   This function does a smooth interpolation of pixel values, so as
  973. *   a result, it re-renders the pixels done on previous passes, so it
  974. *   is about 1/16th slower.  This function will take any tile size, not
  975. *   just powers of two.  The smooth interpolation is conditional, since
  976. *   on some platforms it is quite slow.  When you're doing radiosity,
  977. *   life is slow anyway, so the smooth effect is very nice.
  978. *   Most important difference is that this function does jittering, so
  979. *   that the places at which radiosity tends to be calculated don't lie
  980. *   on a grid and produce unpleasant grid artefacts.
  981. *   This doesn't really have to be a separate function;  the two
  982. *   could be merged.
  983. *
  984. * CHANGES
  985. *
  986. *   Apr 1995 : Created with first radiosity patches
  987. *   Feb 1996 : Made the row buffers dynamically allocated [AED]
  988. *
  989. ******************************************************************************/
  990. void Start_Tracing_Mosaic_Smooth(StartPixelSize, EndPixelSize)
  991. int StartPixelSize, EndPixelSize;
  992. {
  993.   unsigned char Red, Green, Blue, Alpha;
  994.   unsigned char *thisr = NULL, *thisg = NULL, *thisb = NULL, *thisa = NULL;
  995.   unsigned char *upr = NULL, *upg = NULL, *upb = NULL, *upa = NULL;
  996.   int Smooth_Preview = 0;
  997.   int dx, dy, skip,
  998.       tr, tg, tb, ta,
  999.       lastr, lastg, lastb, lasta,
  1000.       ulr, urr, llr, lrr,
  1001.       ulg, urg, llg, lrg,
  1002.       ulb, urb, llb, lrb,
  1003.       ula, ura, lla, lra,
  1004.       lor, log, lob, loa,
  1005.       hir, hig, hib, hia,
  1006.       tx, ty, jitter_range, jitter_offset, offset_x, offset_y, first_pass,
  1007.       x, y, x2, y2;
  1008.   DBL grey, gather_grey;
  1009.   COLOUR Colour, avg_gather;
  1010.  
  1011.   lastr = lastg = lastb = lasta = 0;
  1012.  
  1013.   opts.Radiosity_Error_Bound *= opts.Radiosity_Low_Error_Factor;
  1014.  
  1015.   /* Initialize the accumulators which will allow us to set average amb Brightness */
  1016.   Make_Colour(Radiosity_Gather_Total, 0.0, 0.0, 0.0);
  1017.   Radiosity_Gather_Total_Count = 0;
  1018.  
  1019.   /* if radiosity is on, you MUST use preview pass to get reasonable results.
  1020.    * 8x8 is generally a good size to use if the user didn't specify anything.
  1021.    */
  1022.   if ( StartPixelSize == 1 )  StartPixelSize = EndPixelSize = 8;
  1023.  
  1024.   /* Prevent 2x2 or 1x1 passes - this code is very slow at 2x2 or less */
  1025.   if ( StartPixelSize < 4)  StartPixelSize = 4;
  1026.   if ( EndPixelSize   < 4)  EndPixelSize = 4;
  1027.  
  1028.   /* if there is no visible output, might as well just do one pass, it's faster.
  1029.    * The last pass is the one which determines the values which get put into
  1030.    * the radiosity tree, so just do the last (end) pass.
  1031.    */
  1032.   if ( !(opts.Options & DISPLAY))  StartPixelSize = EndPixelSize;
  1033.  
  1034.   /* Finally, end size must always be less than or equal to start size */
  1035.   if ( EndPixelSize > StartPixelSize ) EndPixelSize = StartPixelSize;
  1036.  
  1037.  
  1038.   skip = StartPixelSize;
  1039.   first_pass = TRUE;
  1040.  
  1041.   if (opts.Options & DISPLAY)
  1042.   {
  1043.     upr = (unsigned char *)POV_MALLOC(opts.Last_Column, "mosaic row buffer");
  1044.     upg = (unsigned char *)POV_MALLOC(opts.Last_Column, "mosaic row buffer");
  1045.     upb = (unsigned char *)POV_MALLOC(opts.Last_Column, "mosaic row buffer");
  1046.     upa = (unsigned char *)POV_MALLOC(opts.Last_Column, "mosaic row buffer");
  1047.  
  1048.     thisr = (unsigned char *)POV_MALLOC(opts.Last_Column, "mosaic row buffer");
  1049.     thisg = (unsigned char *)POV_MALLOC(opts.Last_Column, "mosaic row buffer");
  1050.     thisb = (unsigned char *)POV_MALLOC(opts.Last_Column, "mosaic row buffer");
  1051.     thisa = (unsigned char *)POV_MALLOC(opts.Last_Column, "mosaic row buffer");
  1052.   }
  1053.  
  1054.   while ((skip >= 4) && (skip >= EndPixelSize))
  1055.   {
  1056.     /* for each pass */
  1057.  
  1058.     jitter_range  = 3;
  1059.     jitter_offset = skip / 2 - 1;       /* add a very small amount of jitter */
  1060.  
  1061.     if ( skip <= 8 ) Smooth_Preview = 1;
  1062.  
  1063.     for (y = opts.First_Line; y < opts.Last_Line; y += skip)
  1064.     {
  1065.       check_stats(y, 1, skip);
  1066.  
  1067.       for (x = opts.First_Column; x < opts.Last_Column; x += skip)
  1068.       {
  1069.         Check_User_Abort(FALSE);
  1070.  
  1071.         offset_x = jitter_offset + (POV_RAND() % jitter_range);
  1072.         offset_y = jitter_offset + (POV_RAND() % jitter_range);
  1073.  
  1074.         trace_pixel(x + offset_x, y + offset_y, Colour);
  1075.  
  1076.         extract_colors(Colour, &Red, &Green, &Blue, &Alpha, &grey);
  1077.  
  1078.         Assign_Colour(Current_Line[x], Colour);
  1079.  
  1080.         if (opts.Options & DISPLAY)
  1081.         {
  1082.           if ( Smooth_Preview )
  1083.           {
  1084.             /* if smooth colour blending desired */
  1085.  
  1086.             if (y == opts.First_Line)
  1087.             {
  1088.               upr[x] = Red;
  1089.               upg[x] = Green;
  1090.               upb[x] = Blue;
  1091.               upa[x] = Alpha;
  1092.             }
  1093.  
  1094.             ulr = (x>0) ? upr[x-skip] : Red;
  1095.             urr = upr[x];
  1096.  
  1097.             llr = (x>0) ? lastr   : Red;
  1098.             lrr = Red;
  1099.  
  1100.             ulg = (x>0) ? upg[x-skip] : Green;
  1101.             urg = upg[x];
  1102.  
  1103.             llg = (x>0) ? lastg   : Green;
  1104.             lrg = Green;
  1105.  
  1106.             ulb = (x>0) ? upb[x-skip] : Blue;
  1107.             urb = upb[x];
  1108.  
  1109.             llb = (x>0) ? lastb   : Blue;
  1110.             lrb = Blue;
  1111.  
  1112.             ula = (x>0) ? upa[x-skip] : Alpha;
  1113.             ura = upa[x];
  1114.  
  1115.             lla = (x>0) ? lasta   : Alpha;
  1116.             lra = Alpha;
  1117.  
  1118.             for (ty = y, dy = 0; (dy < skip) && (ty < opts.Last_Line); dy++, ty++)
  1119.             {
  1120.               lor = (ulr * (skip-dy) + llr * dy) / skip;
  1121.               hir = (urr * (skip-dy) + lrr * dy) / skip;
  1122.               log = (ulg * (skip-dy) + llg * dy) / skip;
  1123.               hig = (urg * (skip-dy) + lrg * dy) / skip;
  1124.               lob = (ulb * (skip-dy) + llb * dy) / skip;
  1125.               hib = (urb * (skip-dy) + lrb * dy) / skip;
  1126.               loa = (ula * (skip-dy) + lla * dy) / skip;
  1127.               hia = (ura * (skip-dy) + lra * dy) / skip;
  1128.  
  1129.               for (tx = x, dx = 0; (dx < skip) && (tx < opts.Last_Column); dx++, tx++)
  1130.               {
  1131.                 tr = (lor * (skip - dx) + (hir * dx)) / skip;
  1132.                 tg = (log * (skip - dx) + (hig * dx)) / skip;
  1133.                 tb = (lob * (skip - dx) + (hib * dx)) / skip;
  1134.                 ta = (loa * (skip - dx) + (hia * dx)) / skip;
  1135.  
  1136.                 POV_DISPLAY_PLOT (tx, y+dy, tr, tg, tb, ta);
  1137.               }
  1138.             }
  1139.  
  1140.             thisr[x] = Red;
  1141.             thisg[x] = Green;
  1142.             thisb[x] = Blue;
  1143.             thisa[x] = Alpha;
  1144.  
  1145.             lastr = Red;
  1146.             lastg = Green;
  1147.             lastb = Blue;
  1148.             lasta = Alpha;
  1149.           }
  1150.           else
  1151.           {
  1152.             y2 = min(y + skip - 1, opts.Last_Line);
  1153.             x2 = min(x + skip - 1, opts.Last_Column);
  1154.  
  1155.             POV_DISPLAY_PLOT_RECT(x, x2, y, y2, Red, Green, Blue, Alpha);
  1156.           }
  1157.         }
  1158.       } /* end loop for each block horizontally in a row of blocks */
  1159.  
  1160.       /* Swap the previous and current row buffers */
  1161.       if (opts.Options & DISPLAY)
  1162.       {
  1163.         unsigned char * temp;
  1164.  
  1165.         temp = upr;
  1166.         upr = thisr;
  1167.         thisr = temp;
  1168.  
  1169.         temp = upg;
  1170.         upg = thisg;
  1171.         thisg = temp;
  1172.  
  1173.         temp = upb;
  1174.         upb = thisb;
  1175.         thisb = temp;
  1176.  
  1177.         temp = upa;
  1178.         upa = thisa;
  1179.         thisa = temp;
  1180.       }
  1181.  
  1182.       if (opts.Options & VERBOSE)
  1183.       {
  1184.         if (opts.Options & RADIOSITY)
  1185.         {
  1186.           Status_Info("  %ld radiosity samples", ra_gather_count - RadiosityCount);
  1187.         }
  1188.  
  1189.         Status_Info(".    \r");
  1190.       }
  1191.     } /* end loop of rows of blocks */
  1192.  
  1193.     /*
  1194.      * This adjusts the overall brightness value so that the darkening
  1195.      * effect of the radiosity calculation is cancelled out.
  1196.      */
  1197.  
  1198.     if (first_pass)
  1199.     {
  1200.       /* Ensure that the average ambient value returned by compute_ambient() is about
  1201.        * the same as the average ambient value setting in the scene file
  1202.        */
  1203.  
  1204.       if ( Radiosity_Gather_Total_Count )
  1205.       {
  1206.         VInverseScale(avg_gather,  Radiosity_Gather_Total,  (DBL)Radiosity_Gather_Total_Count);
  1207.         gather_grey  = avg_gather[RED]  + avg_gather[GREEN]  + avg_gather[BLUE];
  1208.         if ( gather_grey > 0. )
  1209.         {
  1210.           opts.Radiosity_Brightness = 3. / gather_grey;
  1211.           if ( ot_fd != NULL)
  1212.           { 
  1213.             fprintf(ot_fd, "B%g\n", opts.Radiosity_Brightness);
  1214.           } 
  1215.         }
  1216.       }
  1217.  
  1218.       first_pass = 0;
  1219.     }
  1220.  
  1221.     skip /= 2;
  1222.   } /* end loop of different resolutions */
  1223.  
  1224.   /* Free our row buffers */
  1225.   if (opts.Options & DISPLAY)
  1226.   {
  1227.     POV_FREE(upr);      upr=NULL;  
  1228.     POV_FREE(upg);      upg=NULL;  
  1229.     POV_FREE(upb);      upb=NULL;  
  1230.     POV_FREE(upa);      upa=NULL;  
  1231.                                           
  1232.     POV_FREE(thisr);    thisr=NULL;
  1233.     POV_FREE(thisg);    thisg=NULL;
  1234.     POV_FREE(thisb);    thisb=NULL;
  1235.     POV_FREE(thisa);    thisa=NULL;
  1236.   }
  1237.  
  1238.   opts.Radiosity_Error_Bound /= opts.Radiosity_Low_Error_Factor;
  1239.  
  1240.   if (opts.Options & VERBOSE)
  1241.   {
  1242.     Status_Info("                                                                      \r");
  1243.   }
  1244.   
  1245.   /* Are we in the process of creating a radiosity cache file? */
  1246.   if ( ot_fd != NULL )
  1247.   {
  1248.     fprintf(ot_fd, "P\n");   /* code meaning that preview pass was completed */
  1249.   }
  1250.   opts.Radiosity_Preview_Done = 1;
  1251. }
  1252.  
  1253.  
  1254. /*****************************************************************************
  1255. *
  1256. * FUNCTION
  1257. *
  1258. *   Start_Non_Adaptive_Tracing
  1259. *
  1260. * INPUT
  1261. *   
  1262. * OUTPUT
  1263. *   
  1264. * RETURNS
  1265. *   
  1266. * AUTHOR
  1267. *
  1268. *   POV-Ray Team
  1269. *   
  1270. * DESCRIPTION
  1271. *
  1272. *   Trace pixels by shooting rays at the center of each pixel. If the
  1273. *   colors between a pixel and its left and/or upper neighbor differ
  1274. *   too much all or some of the pixel are supersampled using a fixed
  1275. *   number of rays.
  1276. *
  1277. * CHANGES
  1278. *
  1279. *   Aug 1994 : Modified to call common extract_colors() fn, Eduard Schwan
  1280. *
  1281. *   Sep 1994 : Added code for vista buffer. [DB]
  1282. *
  1283. *   Aug 1995 : Added Field Rendering for NTSC/PAL Animations, Jeff Bowermaster
  1284. *
  1285. *   Aug 1995 : Added code to jitter pixel location. [DB]
  1286. *
  1287. ******************************************************************************/
  1288.  
  1289. void Start_Non_Adaptive_Tracing()
  1290. {
  1291.   int x, y;
  1292.   int antialias_line = TRUE;
  1293.   int skip_lines;
  1294.   int first_line;
  1295.   int skip_odd_lines;
  1296.  
  1297.   /* Set jitterscale. */
  1298.  
  1299.   JitterScale = opts.JitterScale / (DBL)opts.AntialiasDepth;
  1300.  
  1301.   /* Odd/even line tracing depends on the frame number. */
  1302.  
  1303.   skip_odd_lines = !((opts.FrameSeq.FrameNumber % 2) ^ opts.FrameSeq.Odd_Field_Flag);
  1304.  
  1305.   /* Field rendering starts on an odd or even line. */
  1306.  
  1307.   skip_lines = (opts.FrameSeq.Field_Render_Flag) && !(opts.Options & ANTIALIAS);
  1308.  
  1309.   /* Get first line number. */
  1310.  
  1311.   first_line = (opts.Options & ANTIALIAS)?opts.First_Line-1:opts.First_Line;
  1312.  
  1313.   /* Loop over all rows. */
  1314.  
  1315.   for (y = first_line; y < opts.Last_Line; y++)
  1316.   {
  1317.     /* Skip odd or even lines depending on the line number. */
  1318.  
  1319.     if ((skip_lines) && ((y % 2) == skip_odd_lines))
  1320.     {
  1321.       /* Write previous line again. */
  1322.  
  1323.       if ((opts.Options & DISKWRITE) && (y > opts.First_Line))
  1324.       {
  1325.         Write_Line(Output_File_Handle, Previous_Line, y);
  1326.       }
  1327.  
  1328.       continue;
  1329.     }
  1330.  
  1331.     check_stats(y, 0, 1);
  1332.  
  1333.     /* Prune vista tree. */
  1334.  
  1335.     Prune_Vista_Tree(y);
  1336.  
  1337.     /* Precalculate whether to antialias a line. */
  1338.  
  1339.     if (opts.FrameSeq.Field_Render_Flag)
  1340.     {
  1341.       if (y >= opts.First_Line)
  1342.       {
  1343.         antialias_line = ((y % 2) ^ skip_odd_lines);
  1344.       }
  1345.       else
  1346.       {
  1347.         antialias_line = FALSE;
  1348.       }
  1349.     }
  1350.  
  1351.     /* Loop over all columns. */
  1352.  
  1353.     for (x = opts.First_Column; x < opts.Last_Column; x++)
  1354.     {
  1355.       /* Check for user abort. */
  1356.  
  1357.       Check_User_Abort(FALSE);
  1358.  
  1359.       /* Trace current pixel. */
  1360.  
  1361. /*
  1362.       Debug_Info("y = %3d, x = %3d\n", y, x);
  1363. */
  1364.  
  1365.       trace_pixel(x, y, Current_Line[x]);
  1366.  
  1367.       /* Apply anti-aliasing. */
  1368.  
  1369.       if ((opts.Options & ANTIALIAS) && antialias_line)
  1370.       {
  1371.         do_anti_aliasing(x, y, Current_Line[x]);
  1372.       }
  1373.  
  1374.       /* Display pixel. */
  1375.  
  1376.       plot_pixel(x, y, Current_Line[x]);
  1377.     }
  1378.  
  1379.     /* Write current row to disk. */
  1380.  
  1381.     output_line(y);
  1382.   }
  1383.  
  1384.   /* Write last row to disk. */
  1385.  
  1386.   if (opts.Options & DISKWRITE)
  1387.   {
  1388.     if (opts.Last_Line != opts.First_Line)
  1389.     {
  1390.       Write_Line(Output_File_Handle, Previous_Line, opts.Last_Line - 1);
  1391.     }
  1392.   }
  1393. }
  1394.  
  1395.  
  1396.  
  1397. /*****************************************************************************
  1398. *
  1399. * FUNCTION
  1400. *
  1401. *   Start_Adaptive_Tracing
  1402. *
  1403. * INPUT
  1404. *
  1405. * OUTPUT
  1406. *   
  1407. * RETURNS
  1408. *   
  1409. * AUTHOR
  1410. *
  1411. *   Dieter Bayer
  1412. *   
  1413. * DESCRIPTION
  1414. *
  1415. *   Trace pixels by shooting rays at each corner of a pixel and subdividing
  1416. *   if the colors ate the pixel's corenr differ too much. The subdivision
  1417. *   is made recursively by further subdividing those sub-pixels whose colors
  1418. *   differ too much.
  1419. *
  1420. *   Note that is doesn't make any sense to skip line during field tracing
  1421. *   because samples are taken at the corners of the pixels and are shared
  1422. *   among adjacent lines/pixels. Thus leaving every second line doesn't
  1423. *   save anything. The subdivision is only done on the odd/even lines
  1424. *   depending on the lines to be traced.
  1425. *
  1426. * CHANGES
  1427. *
  1428. *   Jul 1995 : Creation
  1429. *
  1430. *   Aug 1995 : Added field rendering support. [DB]
  1431. *
  1432. ******************************************************************************/
  1433.  
  1434. void Start_Adaptive_Tracing()
  1435. {
  1436.   int x, y, xx, xxx, yy, skip_odd_lines;
  1437.   int sub_pixel_size, antialias_line = TRUE;
  1438.   size_t size;
  1439.   COLOUR Colour;
  1440.   PIXEL *First_Row, *Last_Row, **Block, *TempRow, TempPixel;
  1441.  
  1442.   /* If no antialiasing is specified use non-adaptive sampling. */
  1443.  
  1444.   if (!(opts.Options & ANTIALIAS))
  1445.   {
  1446.     Start_Non_Adaptive_Tracing();
  1447.  
  1448.     return;
  1449.   }
  1450.   
  1451.   /* Init color. */
  1452.  
  1453.   Make_ColourA(Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  1454.  
  1455.   /* Odd/even line tracing depends on the frame number. */
  1456.  
  1457.   skip_odd_lines = !((opts.FrameSeq.FrameNumber % 2) ^ opts.FrameSeq.Odd_Field_Flag);
  1458.  
  1459.   /* Set sub-pixel size to 2**(AntialiasDepth) */
  1460.  
  1461.   sub_pixel_size = 1 << (opts.AntialiasDepth);
  1462.  
  1463.   /* Set jitterscale. */
  1464.  
  1465.   JitterScale = opts.JitterScale / (DBL)(sub_pixel_size+1);
  1466.  
  1467.   /* Allocate row arrays */
  1468.  
  1469.   size = (sub_pixel_size * Frame.Screen_Width + 1) * sizeof(PIXEL);
  1470.  
  1471.   First_Row = (PIXEL *)POV_MALLOC(size, "row buffer");
  1472.   Last_Row  = (PIXEL *)POV_MALLOC(size, "row buffer");
  1473.  
  1474.   /* Allocate block array */
  1475.  
  1476.   Block = (PIXEL **)POV_MALLOC((sub_pixel_size+1) * sizeof(PIXEL *), "block buffer");
  1477.  
  1478.   for (y = 0; y < sub_pixel_size + 1; y++)
  1479.   {
  1480.     Block[y] = (PIXEL *)POV_MALLOC((sub_pixel_size+1) * sizeof(PIXEL), "block buffer");
  1481.   }
  1482.  
  1483.  
  1484.   /**************************************************************************
  1485.    * Init row and block buffer
  1486.    **************************************************************************/
  1487.  
  1488.   for (x = 0; x < sub_pixel_size * Frame.Screen_Width + 1; x++)
  1489.   {
  1490.     First_Row[x].active = FALSE;
  1491.     Last_Row[x].active  = FALSE;
  1492.  
  1493.     Make_ColourA(First_Row[x].Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  1494.     Make_ColourA(Last_Row[x].Colour,  0.0, 0.0, 0.0, 0.0, 0.0);
  1495.   }
  1496.  
  1497.   for (y = 0; y < sub_pixel_size + 1; y++)
  1498.   {
  1499.     for (x = 0; x < sub_pixel_size + 1; x++)
  1500.     {
  1501.       Block[y][x].active = FALSE;
  1502.  
  1503.       Make_ColourA(Block[y][x].Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  1504.     }
  1505.   }
  1506.  
  1507.  
  1508.   /**************************************************************************
  1509.    * Trace all lines, i.e. the image
  1510.    **************************************************************************/
  1511.  
  1512.   for (y = opts.First_Line; y < opts.Last_Line; y++)
  1513.   {
  1514.     check_stats(y, 0, 1);
  1515.  
  1516.     if (opts.Options & USE_VISTA_BUFFER)
  1517.     {
  1518.       Prune_Vista_Tree(y);
  1519.     }
  1520.  
  1521.     /* Set last row inactive */
  1522.  
  1523.     for (xx = 0; xx < sub_pixel_size * Frame.Screen_Width + 1; xx++)
  1524.     {
  1525.       Last_Row[xx].active = FALSE;
  1526.     }
  1527.  
  1528.     /* Set first column inactive */
  1529.  
  1530.     for (yy = 0; yy < sub_pixel_size + 1; yy++)
  1531.     {
  1532.       Block[yy][0].active = FALSE;
  1533.     }
  1534.  
  1535.     /* Precalculate whether to antialias a line. */
  1536.  
  1537.     if (opts.FrameSeq.Field_Render_Flag)
  1538.     {
  1539.       antialias_line = (y % 2) ^ skip_odd_lines;
  1540.     }
  1541.  
  1542.  
  1543.     /************************************************************************
  1544.      * Trace all pixels on the current line
  1545.      ************************************************************************/
  1546.  
  1547.     for (x = opts.First_Column; x < opts.Last_Column; x++)
  1548.     {
  1549.       Check_User_Abort(FALSE);
  1550.  
  1551.       Increase_Counter(stats[Number_Of_Pixels]);
  1552.  
  1553.       /* Initialize current block */
  1554.  
  1555.       for (yy = 1; yy < sub_pixel_size + 1; yy++)
  1556.       {
  1557.         for (xx = 1; xx < sub_pixel_size + 1; xx++)
  1558.         {
  1559.           Block[yy][xx].active = FALSE;
  1560.         }
  1561.       }
  1562.  
  1563.       for (xxx = 0, xx = x * sub_pixel_size; xx < (x+1) * sub_pixel_size + 1; xxx++, xx++)
  1564.       {
  1565.         Block[0][xxx] = First_Row[xx];
  1566.       }
  1567.  
  1568.       /* Do histogram stuff. */
  1569.  
  1570.       if (opts.histogram_on)
  1571.       {
  1572.         accumulate_histogram(x, y, TRUE);
  1573.       }
  1574.  
  1575.       /* Trace pixel centered on (x, y) */
  1576.  
  1577.       trace_sub_pixel(1, Block, x, y, 0, 0, sub_pixel_size, sub_pixel_size, sub_pixel_size, Colour, antialias_line);
  1578.  
  1579.       /* Do histogram stuff. */
  1580.  
  1581.       if (opts.histogram_on)
  1582.       {
  1583.         accumulate_histogram(x, y, FALSE);
  1584.       }
  1585.  
  1586.       /* Store colour in current line */
  1587.  
  1588.       Assign_Colour(Current_Line[x], Colour);
  1589.  
  1590.       /* Display pixel */
  1591.  
  1592.       plot_pixel(x, y, Colour);
  1593.  
  1594.       /* Store current block in rows */
  1595.  
  1596.       for (xxx = 0, xx = x * sub_pixel_size; xx < (x+1) * sub_pixel_size + 1; xxx++, xx++)
  1597.       {
  1598.         First_Row[xx] = Block[0][xxx];
  1599.         Last_Row[xx]  = Block[sub_pixel_size][xxx];
  1600.       }
  1601.  
  1602.       /* Swap first and last block column */
  1603.  
  1604.       for (yy = 0; yy < sub_pixel_size + 1; yy++)
  1605.       {
  1606.         TempPixel                 = Block[yy][0];
  1607.         Block[yy][0]              = Block[yy][sub_pixel_size];
  1608.         Block[yy][sub_pixel_size] = TempPixel;
  1609.       }
  1610.     }
  1611.  
  1612.     output_line(y);
  1613.  
  1614.     /* Swap first and last row */
  1615.  
  1616.     TempRow   = Last_Row;
  1617.     Last_Row  = First_Row;
  1618.     First_Row = TempRow;
  1619.   }
  1620.  
  1621.   /* We've come to the end ... at last! */
  1622.  
  1623.   if (opts.Options & DISKWRITE)
  1624.   {
  1625.     if (opts.Last_Line != opts.First_Line)
  1626.     {
  1627.       Write_Line (Output_File_Handle, Previous_Line, opts.Last_Line - 1);
  1628.     }
  1629.   }
  1630.  
  1631.   /* Free memory. */
  1632.  
  1633.   for (y = 0; y < sub_pixel_size + 1; y++)
  1634.   {
  1635.     POV_FREE(Block[y]);
  1636.   }
  1637.  
  1638.   POV_FREE(Block);
  1639.   POV_FREE(First_Row);
  1640.   POV_FREE(Last_Row);
  1641. }
  1642.  
  1643.  
  1644. /*****************************************************************************
  1645. *
  1646. * FUNCTION
  1647. *
  1648. *   Trace
  1649. *
  1650. * INPUT
  1651. *
  1652. * OUTPUT
  1653. *
  1654. * RETURNS
  1655. *
  1656. *   distance to nearest intersection, or BOUND_HUGE on miss
  1657. *
  1658. * AUTHOR
  1659. *
  1660. *   POV-Ray Team
  1661. *
  1662. * DESCRIPTION
  1663. *
  1664. *   -
  1665. *
  1666. * CHANGES
  1667. *
  1668. *   Nov 1994 : Rearranged calls to Fog, Rainbow and Skyblend.
  1669. *              Added call to Atmosphere for atmospheric effects. [DB]
  1670. *   Jan 1995 : Set intersection depth to Max_Distance for infinite rays. [DB]
  1671. *   Mar 1995 : Added return value for radiosity work [JDM]
  1672. *   Jul 1995 : Added code to support alpha channel. [DB]
  1673. *
  1674. ******************************************************************************/
  1675.  
  1676. DBL Trace(Ray, Colour, Weight)
  1677. RAY *Ray;
  1678. COLOUR Colour;
  1679. DBL Weight;
  1680. {
  1681.   int i, Intersection_Found, all_hollow;
  1682.   OBJECT *Object;
  1683.   INTERSECTION Best_Intersection, New_Intersection;
  1684.  
  1685.   COOPERATE_0
  1686.  
  1687.   Increase_Counter(stats[Number_Of_Rays]);
  1688.  
  1689.   /* Transmittance has to be 1 to make alpha channel output to work. [DB] */
  1690.  
  1691.   Make_ColourA(Colour, 0.0, 0.0, 0.0, 0.0, 1.0);
  1692.  
  1693.   /* Check for max. trace level or ADC bailout. */
  1694.  
  1695.   if ((Trace_Level > Max_Trace_Level) || (Weight < ADC_Bailout))
  1696.   {
  1697.     if (Weight < ADC_Bailout)
  1698.     {
  1699.       Increase_Counter(stats[ADC_Saves]);
  1700.     }
  1701.  
  1702.     return (BOUND_HUGE);
  1703.   }
  1704.  
  1705.   /* Set highest level traced. */
  1706.  
  1707.   if (Trace_Level > Highest_Trace_Level)
  1708.   {
  1709.     Highest_Trace_Level = Trace_Level;
  1710.   }
  1711.  
  1712.   /* What objects does this ray intersect? */
  1713.  
  1714.   Intersection_Found = FALSE;
  1715.  
  1716.   Best_Intersection.Depth = BOUND_HUGE;
  1717.  
  1718.   if (!opts.Use_Slabs)
  1719.   {
  1720.     for (Object = Frame.Objects; Object != NULL; Object = Object -> Sibling)
  1721.     {
  1722.       if (Intersection(&New_Intersection, Object, Ray))
  1723.       {
  1724.         if (New_Intersection.Depth < Best_Intersection.Depth)
  1725.         {
  1726.           Best_Intersection = New_Intersection;
  1727.  
  1728.           Intersection_Found = TRUE;
  1729.         }
  1730.       }
  1731.     }
  1732.   }
  1733.   else
  1734.   {
  1735.     Intersection_Found = Intersect_BBox_Tree(Root_Object, Ray,
  1736.            &Best_Intersection, &Object);
  1737.   }
  1738.  
  1739.   /* Get color for this ray. */
  1740.  
  1741.   if (Intersection_Found)
  1742.   {
  1743.     /* Determine colour of object hit. */
  1744.  
  1745.     Determine_Apparent_Colour(&Best_Intersection, Colour, Ray, Weight);
  1746.   }
  1747.   else
  1748.   {
  1749.       /* Infinite ray, set intersecton distance. */
  1750.  
  1751.       Best_Intersection.Depth = Max_Distance;
  1752.  
  1753.       /* Apply infinite atmospheric effects. */
  1754.  
  1755.       Do_Infinite_Atmosphere(Ray, Colour);
  1756.   }
  1757.  
  1758.   /* Test if all contained objects are hollow. */
  1759.  
  1760.   all_hollow = TRUE;
  1761.  
  1762.   if (Ray->Containing_Index > -1)
  1763.   {
  1764.     for (i = 0; i <= Ray->Containing_Index; i++)
  1765.     {
  1766.       if (!Test_Flag(Ray->Containing_Objects[i], HOLLOW_FLAG))
  1767.       {
  1768.         all_hollow = FALSE;
  1769.  
  1770.         break;
  1771.       }
  1772.     }
  1773.   }
  1774.  
  1775.   /* Apply finite atmospheric effects. */
  1776.  
  1777.   if (all_hollow)
  1778.   {
  1779.     Do_Finite_Atmosphere(Ray, &Best_Intersection, Colour, FALSE);
  1780.   }
  1781.  
  1782.   return (Best_Intersection.Depth);
  1783. }
  1784.  
  1785.  
  1786.  
  1787. /*****************************************************************************
  1788. *
  1789. * FUNCTION
  1790. *
  1791. *   do_anti_aliasing
  1792. *
  1793. * INPUT
  1794. *
  1795. * OUTPUT
  1796. *
  1797. * RETURNS
  1798. *
  1799. * AUTHOR
  1800. *
  1801. *   POV-Ray Team
  1802. *
  1803. * DESCRIPTION
  1804. *
  1805. *   -
  1806. *
  1807. * CHANGES
  1808. *
  1809. *   Aug 1995 : Modified to avoid unnecessary pixel output. [DB]
  1810. *
  1811. *   Aug 1995 : Modified to avoid supersampling of unused lines
  1812. *              when using field tracing. [DB]
  1813. *
  1814. ******************************************************************************/
  1815.  
  1816. static void do_anti_aliasing(x, y, Colour)
  1817. register int x, y;
  1818. COLOUR Colour;
  1819. {
  1820.   char Antialias_Center_Flag = FALSE;
  1821.  
  1822.   Current_Line_Antialiased_Flags[x] = FALSE;
  1823.  
  1824.   /* Test difference to pixel left of current pixel. */
  1825.  
  1826.   if (x != 0)
  1827.   {
  1828.     if (Colour_Distance(Current_Line[x-1],Current_Line[x]) >= Frame.Antialias_Threshold)
  1829.     {
  1830.       Antialias_Center_Flag = TRUE;
  1831.  
  1832.       if (!(Current_Line_Antialiased_Flags[x-1]))
  1833.       {
  1834.         supersample(Current_Line[x-1], x-1, y);
  1835.  
  1836.         Current_Line_Antialiased_Flags[x-1] = TRUE;
  1837.  
  1838.         SuperSampleCount++;
  1839.  
  1840.         plot_pixel(x-1, y, Current_Line[x-1]);
  1841.  
  1842.         COOPERATE_1
  1843.       }
  1844.     }
  1845.   }
  1846.  
  1847.   /* Test difference to pixel above current pixel. */
  1848.  
  1849.   if ((y != opts.First_Line-1) && (!opts.FrameSeq.Field_Render_Flag))
  1850.   {
  1851.     if (Colour_Distance(Previous_Line[x],Current_Line[x]) >= Frame.Antialias_Threshold)
  1852.     {
  1853.       Antialias_Center_Flag = TRUE;
  1854.  
  1855.       if (!(Previous_Line_Antialiased_Flags[x]))
  1856.       {
  1857.         supersample(Previous_Line[x], x, y-1);
  1858.  
  1859.         Previous_Line_Antialiased_Flags[x] = TRUE;
  1860.  
  1861.         SuperSampleCount++;
  1862.  
  1863.         plot_pixel(x, y, Previous_Line[x]);
  1864.  
  1865.         COOPERATE_1
  1866.       }
  1867.     }
  1868.   }
  1869.  
  1870.   /* Supersample current pixel if necessary. */
  1871.  
  1872.   if (Antialias_Center_Flag)
  1873.   {
  1874.     supersample(Current_Line[x], x, y);
  1875.  
  1876.     Current_Line_Antialiased_Flags[x] = TRUE;
  1877.  
  1878.     Assign_Colour(Colour, Current_Line[x]);
  1879.  
  1880.     SuperSampleCount++;
  1881.  
  1882.     COOPERATE_1
  1883.   }
  1884. }
  1885.  
  1886.  
  1887.  
  1888. /*****************************************************************************
  1889. *
  1890. * FUNCTION
  1891. *
  1892. *   supersample
  1893. *
  1894. * INPUT
  1895. *   
  1896. * OUTPUT
  1897. *   
  1898. * RETURNS
  1899. *   
  1900. * AUTHOR
  1901. *
  1902. *   POV-Ray Team
  1903. *   
  1904. * DESCRIPTION
  1905. *
  1906. *   Standard sampling in loop
  1907. *
  1908. * CHANGES
  1909. *
  1910. *   Aug 1995 : Modified to avoid resampling of center sub-pixel. [DB]
  1911. *
  1912. *   Sep 1995 : Weight of a primary ray has to be 1 regardless of its
  1913. *              contribution to a supersampled pixel! [DB]
  1914. *
  1915. ******************************************************************************/
  1916.  
  1917. static void supersample(result, x, y)
  1918. COLOUR result;
  1919. int x, y;
  1920. {
  1921.   int i, j, samples;
  1922.   int JRange, JSteps;
  1923.   DBL JSize, JScale;
  1924.   DBL Jitter_X, Jitter_Y;
  1925.   DBL dx, dy;
  1926.   DBL save_radiosity_error_bound;
  1927.   COLOUR colour;
  1928.  
  1929.   /* Why are we here? */
  1930.  
  1931.   if (opts.AntialiasDepth <= 1)
  1932.   {
  1933.     return;
  1934.   }
  1935.  
  1936.   Increase_Counter(stats[Number_Of_Pixels_Supersampled]);
  1937.  
  1938.   /* Number of samples in pixel (used to scale resulting color). */
  1939.  
  1940.   samples = 1;
  1941.  
  1942.   /* Substantially reduces chances of doing new samples. */
  1943.  
  1944.   save_radiosity_error_bound = opts.Radiosity_Error_Bound;
  1945.  
  1946.   opts.Radiosity_Error_Bound *= 2.0;
  1947.  
  1948.   /* JSize is the size of the jitter scattering area */
  1949.  
  1950.   JSize = 1.0 / opts.AntialiasDepth;
  1951.  
  1952.   /*
  1953.    * JSteps is either 1 or 2 depending on whether the number of samples
  1954.    * is odd or even. This is because the loop need to either run through
  1955.    * or over 0.
  1956.    */
  1957.  
  1958.   JSteps = 2 - (opts.AntialiasDepth % 2);
  1959.  
  1960.   /*
  1961.    * JRange is the range that the loop will run through. I couldn't
  1962.    * come up with a function describing the values, so I used an array
  1963.    * for 2x2 up to 9x9.
  1964.    */
  1965.  
  1966.   JRange = JRanges[opts.AntialiasDepth];
  1967.  
  1968.   /*
  1969.    * JScale is the value with which the current sub-pixel indices
  1970.    * (i,j) have to be scaled to get the real sub-pixel positions.
  1971.    */
  1972.  
  1973.   JScale = JSize / (DBL)JSteps;
  1974.  
  1975.   /* Loop over all sub-pixels. */
  1976.  
  1977.   for (i = -JRange; i <= JRange; i += JSteps)
  1978.   {
  1979.     for (j = -JRange; j <= JRange; j += JSteps)
  1980.     {
  1981.       /* Skip center sub-pixel because we already traced it. */
  1982.  
  1983.       if ((i == 0) && (j == 0))
  1984.       {
  1985.         continue;
  1986.       }
  1987.  
  1988.       /* Increase number of samples. */
  1989.  
  1990.       samples++;
  1991.  
  1992.       /* Jitter grid location. */
  1993.  
  1994.       jitter_pixel_position(x, y, &Jitter_X, &Jitter_Y);
  1995.  
  1996.       /* Trace ray through current sub-pixel. */
  1997.  
  1998.       dx = Jitter_X + i * JScale;
  1999.       dy = Jitter_Y + j * JScale;
  2000.  
  2001.       if (create_ray(&Camera_Ray, (DBL)x+dx, (DBL)y+dy, 0))
  2002.       {
  2003.         Trace_Level = 1;
  2004.  
  2005.         Increase_Counter(stats[Number_Of_Samples]);
  2006.  
  2007.         if (opts.Options & USE_VISTA_BUFFER)
  2008.         {
  2009.           Trace_Primary_Ray(&Camera_Ray, colour, 1.0, x);
  2010.         }
  2011.         else
  2012.         {
  2013.           Trace(&Camera_Ray, colour, 1.0);
  2014.         }
  2015.  
  2016.         Clip_Colour(colour, colour);
  2017.  
  2018.         gamma_correct(colour);
  2019.  
  2020.         Add_Colour(result, result, colour);
  2021.       }
  2022.       else
  2023.       {
  2024.         Make_ColourA(colour, 0.0, 0.0, 0.0, 0.0, 1.0);
  2025.       }
  2026.     }
  2027.   }
  2028.  
  2029.   /* Average pixel's color. */
  2030.  
  2031.   Scale_Colour(result, result, 1.0 / (DBL)samples);
  2032.  
  2033.   opts.Radiosity_Error_Bound = save_radiosity_error_bound;
  2034. }
  2035.  
  2036.  
  2037. /*****************************************************************************
  2038. *
  2039. * FUNCTION
  2040. *
  2041. *   trace_sub_pixel
  2042. *
  2043. * INPUT
  2044. *
  2045. *   level     - current subdivision level
  2046. *   Block     - sub-pixel information of current pixel
  2047. *   x, y      - current pixel
  2048. *   x1, y1    - upper left corner of current sub-pixel
  2049. *   x3, y3    - lower right corner of current sub-pixel
  2050. *   size      - sub-pixel size
  2051. *   antialias - TRUE if antialiasing is allowed
  2052. *
  2053. * OUTPUT
  2054. *
  2055. *   Colour   - (sub-)pixels color
  2056. *
  2057. * RETURNS
  2058. *
  2059. * AUTHOR
  2060. *
  2061. *   Dieter Bayer
  2062. *
  2063. * DESCRIPTION
  2064. *
  2065. *   Trace rays at the corners of the (sub-)pixel. If the colors differ
  2066. *   too much and the max. recursion level isn't reached yet subdivide
  2067. *   pixel into four sub-pixel and trace those.
  2068. *
  2069. * CHANGES
  2070. *
  2071. *   Jul 1995 : Creation.
  2072. *
  2073. ******************************************************************************/
  2074.  
  2075. static void trace_sub_pixel(level, Block, x, y, x1, y1, x3, y3, size, Colour, antialias)
  2076. int level;
  2077. PIXEL **Block;
  2078. int x, y, x1, y1, x3, y3, size;
  2079. COLOUR Colour;
  2080. int antialias;
  2081. {
  2082.   int x2, y2;    /* Coordinates of center sub-pixel of current block.     */
  2083.   DBL dx1, dy1;  /* coord. of upper left corner relative to pixel coord.  */
  2084.   DBL dx3, dy3;  /* coord. of lower right corner relative to pixel coord. */
  2085.   COLOUR C1, C2, C3, C4;
  2086.  
  2087.   /* Get offsets for corner pixels. */
  2088.  
  2089.   dx1 = (DBL)(x1 - size / 2) / (DBL)size;
  2090.   dx3 = (DBL)(x3 - size / 2) / (DBL)size;
  2091.  
  2092.   dy1 = (DBL)(y1 - size / 2) / (DBL)size;
  2093.   dy3 = (DBL)(y3 - size / 2) / (DBL)size;
  2094.  
  2095.   /* Trace upper left corner pixel. */
  2096.  
  2097.   if (!Block[y1][x1].active)
  2098.   {
  2099.     trace_ray_with_offset(x, y, dx1, dy1, C1);
  2100.  
  2101.     Block[y1][x1].active = TRUE;
  2102.  
  2103.     Assign_Colour(Block[y1][x1].Colour, C1);
  2104.   }
  2105.   else
  2106.   {
  2107.     Assign_Colour(C1, Block[y1][x1].Colour);
  2108.   }
  2109.  
  2110.   /* Trace lower left corner pixel. */
  2111.  
  2112.   if (!Block[y3][x1].active)
  2113.   {
  2114.     trace_ray_with_offset(x, y, dx1, dy3, C2);
  2115.  
  2116.     Block[y3][x1].active = TRUE;
  2117.  
  2118.     Assign_Colour(Block[y3][x1].Colour, C2);
  2119.   }
  2120.   else
  2121.   {
  2122.     Assign_Colour(C2, Block[y3][x1].Colour);
  2123.   }
  2124.  
  2125.   /* Trace upper right corner pixel. */
  2126.  
  2127.   if (!Block[y1][x3].active)
  2128.   {
  2129.     trace_ray_with_offset(x, y, dx3, dy1, C3);
  2130.  
  2131.     Block[y1][x3].active = TRUE;
  2132.  
  2133.     Assign_Colour(Block[y1][x3].Colour, C3);
  2134.   }
  2135.     else
  2136.   {
  2137.     Assign_Colour(C3, Block[y1][x3].Colour);
  2138.   }
  2139.  
  2140.   /* Trace lower right corner pixel. */
  2141.  
  2142.   if (!Block[y3][x3].active)
  2143.   {
  2144.     trace_ray_with_offset(x, y, dx3, dy3, C4);
  2145.  
  2146.     Block[y3][x3].active = TRUE;
  2147.  
  2148.     Assign_Colour(Block[y3][x3].Colour, C4);
  2149.   }
  2150.   else
  2151.   {
  2152.     Assign_Colour(C4, Block[y3][x3].Colour);
  2153.   }
  2154.  
  2155.   /* Do we have to check for supersampling? */
  2156.  
  2157.   if (antialias && (level <= opts.AntialiasDepth))
  2158.   {
  2159.     /* Check if upper left sub-block should be supersampled. */
  2160.  
  2161.     if ((Colour_Distance(C1, C2) >= Frame.Antialias_Threshold) ||
  2162.         (Colour_Distance(C2, C4) >= Frame.Antialias_Threshold) ||
  2163.         (Colour_Distance(C3, C4) >= Frame.Antialias_Threshold) ||
  2164.         (Colour_Distance(C1, C3) >= Frame.Antialias_Threshold) ||
  2165.         (Colour_Distance(C1, C4) >= Frame.Antialias_Threshold) ||
  2166.         (Colour_Distance(C2, C3) >= Frame.Antialias_Threshold))
  2167.     {
  2168.       /* Get coordinates of center sub-pixel. */
  2169.  
  2170.       x2 = (x1 + x3) / 2;
  2171.       y2 = (y1 + y3) / 2;
  2172.  
  2173.       /* Trace the four sub-blocks. */
  2174.  
  2175.       trace_sub_pixel(level+1, Block, x, y, x1, y1, x2, y2, size, C1, antialias);
  2176.       trace_sub_pixel(level+1, Block, x, y, x1, y2, x2, y3, size, C2, antialias);
  2177.       trace_sub_pixel(level+1, Block, x, y, x2, y1, x3, y2, size, C3, antialias);
  2178.       trace_sub_pixel(level+1, Block, x, y, x2, y2, x3, y3, size, C4, antialias);
  2179.  
  2180.       if (level == 1)
  2181.       {
  2182.         SuperSampleCount++;
  2183.       }
  2184.     }
  2185.   }
  2186.  
  2187.   /* Average sub-block colors. */
  2188.  
  2189.   Colour[RED]    = 0.25 * (C1[RED]    + C2[RED]    + C3[RED]    + C4[RED]);
  2190.   Colour[GREEN]  = 0.25 * (C1[GREEN]  + C2[GREEN]  + C3[GREEN]  + C4[GREEN]);
  2191.   Colour[BLUE]   = 0.25 * (C1[BLUE]   + C2[BLUE]   + C3[BLUE]   + C4[BLUE]);
  2192.   Colour[TRANSM] = 0.25 * (C1[TRANSM] + C2[TRANSM] + C3[TRANSM] + C4[TRANSM]);
  2193. }
  2194.  
  2195.  
  2196. /*****************************************************************************
  2197. *
  2198. * FUNCTION
  2199. *
  2200. *   trace_ray_with_offset
  2201. *
  2202. * INPUT
  2203. *
  2204. * OUTPUT
  2205. *
  2206. * RETURNS
  2207. *
  2208. * AUTHOR
  2209. *
  2210. *   Dieter Bayer
  2211. *
  2212. * DESCRIPTION
  2213. *
  2214. *   Trace a ray through the pixel at (x,y) with an offset (dx,dy)
  2215. *
  2216. * CHANGES
  2217. *
  2218. *   May 1994 : Creation.
  2219. *
  2220. *   Sep 1995 : Weight of a primary ray has to be 1 regardless of its
  2221. *              contribution to a supersampled pixel! [DB]
  2222. *
  2223. ******************************************************************************/
  2224.  
  2225. static void trace_ray_with_offset(x, y, dx, dy, Colour)
  2226. int x, y;
  2227. DBL dx, dy;
  2228. COLOUR Colour;
  2229. {
  2230.   DBL Jitter_X, Jitter_Y;
  2231.  
  2232.   if (Focal_Blur_Is_Used)
  2233.   {
  2234.     focal_blur(&Camera_Ray, Colour, (DBL)x, (DBL)y);
  2235.   }
  2236.   else
  2237.   {
  2238.     /* Jitter the ray */
  2239.  
  2240.     if (opts.Options & ANTIALIAS)
  2241.     {
  2242.       jitter_pixel_position(x, y, &Jitter_X, &Jitter_Y);
  2243.     }
  2244.     else
  2245.     {
  2246.       Jitter_X = Jitter_Y = 0.0;
  2247.     }
  2248.  
  2249.     if (create_ray (&Camera_Ray, (DBL)x+dx+Jitter_X, (DBL)y+dy+Jitter_Y, 0))
  2250.     {
  2251.       Trace_Level = 1;
  2252.  
  2253.       Increase_Counter(stats[Number_Of_Samples]);
  2254.  
  2255.       if (opts.Options & USE_VISTA_BUFFER)
  2256.       {
  2257.         Trace_Primary_Ray(&Camera_Ray, Colour, 1.0, x);
  2258.       }
  2259.       else
  2260.       {
  2261.         Trace(&Camera_Ray, Colour, 1.0);
  2262.       }
  2263.  
  2264.       Clip_Colour(Colour, Colour);
  2265.  
  2266.       gamma_correct(Colour);
  2267.     }
  2268.     else
  2269.     {
  2270.       Make_ColourA(Colour, 0.0, 0.0, 0.0, 0.0, 1.0);
  2271.     }
  2272.   }
  2273. }
  2274.  
  2275.  
  2276.  
  2277. /*****************************************************************************
  2278. *
  2279. * FUNCTION
  2280. *
  2281. *   focal_blur
  2282. *
  2283. * INPUT
  2284. *   
  2285. * OUTPUT
  2286. *   
  2287. * RETURNS
  2288. *   
  2289. * AUTHOR
  2290. *
  2291. *   POV-Ray Team
  2292. *   
  2293. * DESCRIPTION
  2294. *
  2295. *   Calls create_ray(), which calls jitter_camera_ray() to apply the
  2296. *   correct amount of jitter to the ray.  This routine merely sends out
  2297. *   the correct number of rays and averages them into Colour.
  2298. *
  2299. * CHANGES
  2300. *
  2301. *   Jul 1995 : Added code to use a different sub-pixel location for
  2302. *              each sample. Added code to do a statistic confident
  2303. *              test to make early exists possible. [DB]
  2304. *
  2305. ******************************************************************************/
  2306.  
  2307. static void focal_blur(Ray, Colour, x, y)
  2308. RAY *Ray;
  2309. COLOUR Colour;
  2310. DBL x, y;
  2311. {
  2312.   int nr;     /* Number of current samples. */
  2313.   int level;  /* Index into number of samples list. */
  2314.   int max_s;  /* Number of samples to take before next confidence test. */
  2315.   int dxi, dyi;
  2316.   int i;
  2317.   DBL dx, dy, n;
  2318.   COLOUR C, V1, S1, S2;
  2319.  
  2320.   Make_ColourA(Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  2321.  
  2322.   Make_ColourA(V1, 0.0, 0.0, 0.0, 0.0, 0.0);
  2323.  
  2324.   Make_ColourA(S1, 0.0, 0.0, 0.0, 0.0, 0.0);
  2325.  
  2326.   Make_ColourA(S2, 0.0, 0.0, 0.0, 0.0, 0.0);
  2327.  
  2328.   nr = 0;
  2329.  
  2330.   level = 0;
  2331.  
  2332.   do
  2333.   {
  2334.     /* Trace number of rays given by the list Current_Number_Of_Samples[]. */
  2335.  
  2336.     max_s = 4;
  2337.  
  2338.     if (Current_Number_Of_Samples != NULL)
  2339.     {
  2340.       if (Current_Number_Of_Samples[level] > 0)
  2341.       {
  2342.         max_s = Current_Number_Of_Samples[level];
  2343.  
  2344.         level++;
  2345.       }
  2346.     }
  2347.  
  2348.     for (i = 0; (i < max_s) && (nr < Frame.Camera->Blur_Samples); i++)
  2349.     {
  2350.       /* Choose sub-pixel location. */
  2351.  
  2352.       dxi = POV_RAND() % SUB_PIXEL_GRID_SIZE;
  2353.       dyi = POV_RAND() % SUB_PIXEL_GRID_SIZE;
  2354.  
  2355.       dx = (DBL)(2 * dxi + 1) / (DBL)(2 * SUB_PIXEL_GRID_SIZE) - 0.5;
  2356.       dy = (DBL)(2 * dyi + 1) / (DBL)(2 * SUB_PIXEL_GRID_SIZE) - 0.5;
  2357.  
  2358.       /* Add jitter to sub-pixel location. */
  2359.  
  2360.       dx += (FRAND() - 0.5) / (DBL)(SUB_PIXEL_GRID_SIZE);
  2361.       dy += (FRAND() - 0.5) / (DBL)(SUB_PIXEL_GRID_SIZE);
  2362.  
  2363.       /* Create and trace ray. */
  2364.  
  2365.       if (create_ray(Ray, x+dx, y+dy, nr))
  2366.       {
  2367.         Trace_Level = 1;
  2368.  
  2369.         Increase_Counter(stats[Number_Of_Samples]);
  2370.  
  2371.         Trace(Ray, C, 1.0);
  2372.  
  2373.         Clip_Colour(C, C);
  2374.  
  2375.         gamma_correct(C);
  2376.  
  2377.         Add_Colour(Colour, Colour, C);
  2378.       }
  2379.       else
  2380.       {
  2381.         Make_ColourA(C, 0.0, 0.0, 0.0, 0.0, 1.0);
  2382.       }
  2383.  
  2384.       /* Add color to color sum. */
  2385.  
  2386.       S1[RED]    += C[RED];
  2387.       S1[GREEN]  += C[GREEN];
  2388.       S1[BLUE]   += C[BLUE];
  2389.       S1[TRANSM] += C[TRANSM];
  2390.  
  2391.       /* Add color to squared color sum. */
  2392.  
  2393.       S2[RED]    += Sqr(C[RED]);
  2394.       S2[GREEN]  += Sqr(C[GREEN]);
  2395.       S2[BLUE]   += Sqr(C[BLUE]);
  2396.       S2[TRANSM] += Sqr(C[TRANSM]);
  2397.  
  2398.       nr++;
  2399.     }
  2400.  
  2401.     /* Get variance of samples. */
  2402.  
  2403.     n = (DBL)nr;
  2404.  
  2405.     V1[RED]    = (S2[RED]    / n - Sqr(S1[RED]    / n)) / n;
  2406.     V1[GREEN]  = (S2[GREEN]  / n - Sqr(S1[GREEN]  / n)) / n;
  2407.     V1[BLUE]   = (S2[BLUE]   / n - Sqr(S1[BLUE]   / n)) / n;
  2408.     V1[TRANSM] = (S2[TRANSM] / n - Sqr(S1[TRANSM] / n)) / n;
  2409.  
  2410.     /* Exit if samples are likely too be good enough. */
  2411.  
  2412.     if ((V1[RED]  < Sample_Threshold[nr-1]) && (V1[GREEN]  < Sample_Threshold[nr-1]) &&
  2413.         (V1[BLUE] < Sample_Threshold[nr-1]) && (V1[TRANSM] < Sample_Threshold[nr-1]))
  2414.     {
  2415.       break;
  2416.     }
  2417.   }
  2418.   while (nr < Frame.Camera->Blur_Samples);
  2419.  
  2420.   Scale_Colour(Colour, Colour, 1.0 / (DBL)nr);
  2421. }
  2422.  
  2423.  
  2424.  
  2425. /*****************************************************************************
  2426. *
  2427. * FUNCTION
  2428. *
  2429. *   jitter_camera_ray
  2430. *
  2431. * INPUT
  2432. *   
  2433. * OUTPUT
  2434. *   
  2435. * RETURNS
  2436. *   
  2437. * AUTHOR
  2438. *
  2439. *   POV-Ray Team
  2440. *   
  2441. * DESCRIPTION
  2442. *
  2443. *   This routine will deflect eye rays only, since it relies on picking
  2444. *   up viewpoint information from the "Frame" variable.
  2445. *
  2446. *   A hexagonal jitter grid is used if number of blur rays is one of
  2447. *   7, 19, or 37, although this should probably be done differently.
  2448. *
  2449. * CHANGES
  2450. *
  2451. *   -
  2452. *
  2453. ******************************************************************************/
  2454.  
  2455. static void jitter_camera_ray(ray, ray_number)
  2456. RAY *ray;
  2457. int ray_number;
  2458. {
  2459.   DBL xjit, yjit, xlen, ylen, r;
  2460.   VECTOR temp_xperp, temp_yperp, deflection;
  2461.  
  2462.   r = Frame.Camera->Aperture * 0.5;
  2463.  
  2464.   xjit = Max_Jitter * ((FRAND() * 2.0) - 1.0);
  2465.   yjit = Max_Jitter * ((FRAND() * 2.0) - 1.0);
  2466.  
  2467.   xlen = r * (Sample_Grid[ray_number].x + xjit);
  2468.   ylen = r * (Sample_Grid[ray_number].y + yjit);
  2469.  
  2470.   /*
  2471.    * Deflect the position of the eye by the size of the aperture, and in
  2472.    * a direction perpendicular to the current direction of view.
  2473.    */
  2474.  
  2475.   VScale(temp_xperp, XPerp, xlen);
  2476.   VScale(temp_yperp, YPerp, ylen);
  2477.  
  2478.   VSub(deflection, temp_xperp, temp_yperp);
  2479.  
  2480.   VAdd(ray->Initial, Frame.Camera->Location, deflection);
  2481.  
  2482.   /*
  2483.    * Deflect the direction of the ray in the opposite direction we deflected
  2484.    * the eye position.  This makes sure that we are looking at the same place
  2485.    * when the distance from the eye is equal to "Focal_Distance".
  2486.    */
  2487.  
  2488.   VScale(ray->Direction, ray->Direction, Focal_Distance);
  2489.   VSub(ray->Direction, ray->Direction, deflection);
  2490.  
  2491.   VNormalize(ray->Direction, ray->Direction);
  2492. }
  2493.  
  2494.  
  2495.  
  2496. /*****************************************************************************
  2497. *
  2498. * FUNCTION
  2499. *
  2500. *   trace_pixel
  2501. *
  2502. * INPUT
  2503. *   
  2504. * OUTPUT
  2505. *   
  2506. * RETURNS
  2507. *   
  2508. * AUTHOR
  2509. *
  2510. *   POV-Ray Team
  2511. *   
  2512. * DESCRIPTION
  2513. *
  2514. *   Trace a primary ray regarding focal blur and vista buffer.
  2515. *   The color of the pixel is clipped and the number of pixels is increased.
  2516. *
  2517. * CHANGES
  2518. *
  2519. *   Sep 1994 : Extracted common code. [DB]
  2520. *   Jan 1995 : Added call to accumulate_histogram() - Chris Cason
  2521. *
  2522. ******************************************************************************/
  2523.  
  2524. static void trace_pixel(x, y, Colour)
  2525. int x, y;
  2526. COLOUR Colour;
  2527. {
  2528.   Increase_Counter(stats[Number_Of_Pixels]);
  2529.  
  2530.   Trace_Level = 1;
  2531.  
  2532.   POV_PRE_PIXEL (x, y, Colour)
  2533.  
  2534.   COOPERATE_0
  2535.  
  2536.   /* Do histogram stuff. */
  2537.   if (opts.histogram_on)
  2538.   {
  2539.     accumulate_histogram(x, y, TRUE);
  2540.   }
  2541.  
  2542.   if (Focal_Blur_Is_Used)
  2543.   {
  2544.     /* Use focal blur tracing. */
  2545.  
  2546.     focal_blur(&Camera_Ray, Colour, (DBL)x, (DBL)y);
  2547.   }
  2548.   else
  2549.   {
  2550.     /* Create and trace ray. */
  2551.  
  2552.     if (create_ray(&Camera_Ray, (DBL)x, (DBL)y, 0))
  2553.     {
  2554.       Increase_Counter(stats[Number_Of_Samples]);
  2555.  
  2556.       if (opts.Options & USE_VISTA_BUFFER)
  2557.       {
  2558.         Trace_Primary_Ray(&Camera_Ray, Colour, 1.0, x);
  2559.       }
  2560.       else
  2561.       {
  2562.         Trace(&Camera_Ray, Colour, 1.0);
  2563.       }
  2564.     }
  2565.     else
  2566.     {
  2567.       Make_ColourA(Colour, 0.0, 0.0, 0.0, 0.0, 1.0);
  2568.     }
  2569.   }
  2570.  
  2571.   Clip_Colour(Colour, Colour);
  2572.  
  2573.   gamma_correct(Colour);
  2574.  
  2575.   /* Do histogram stuff. */
  2576.   if (opts.histogram_on)
  2577.   {
  2578.     accumulate_histogram(x, y, FALSE);
  2579.   }
  2580.  
  2581.   POV_POST_PIXEL (x, y, Colour)
  2582. }
  2583.  
  2584.  
  2585. /*****************************************************************************
  2586. *
  2587. * FUNCTION
  2588. *
  2589. *   create_ray
  2590. *
  2591. * INPUT
  2592. *
  2593. *   ray        - Primary ray for given screen point
  2594. *   x, y       - Coordinates of current pixel
  2595. *   ray_number - number of ray used by jitter_camera_ray()
  2596. *   
  2597. * OUTPUT
  2598. *
  2599. *   ray
  2600. *   
  2601. * RETURNS
  2602. *
  2603. *   int - TRUE, if a ray was created
  2604. *   
  2605. * AUTHOR
  2606. *
  2607. *   Dieter Bayer
  2608. *   Dan Farmer (focal blur, 'ultra wide angle camera')
  2609. *   
  2610. * DESCRIPTION
  2611. *
  2612. *   Create a primary ray depending on the camera model used.
  2613. *
  2614. *   Ideas for the camera models were taken from:
  2615. *
  2616. *     Geoff Wyvill and Craig McNaughton, "Optical Models",
  2617. *     CG International '90, Springer, 1990, p. 83-93
  2618. *
  2619. *     F. Kenton Musgrave, "A panoramic virtual screen for ray tracing",
  2620. *     Graphics Gems III, David Kirk (eds.), p. 288-294
  2621. *
  2622. * CHANGES
  2623. *
  2624. *   May 1994 : Creation.
  2625. *
  2626. *   Aug 1996 : Removed unnecessary width/height parameters. [DB]
  2627. *
  2628. ******************************************************************************/
  2629.  
  2630. static int create_ray(Ray, x, y, ray_number)
  2631. RAY *Ray;
  2632. DBL x, y;
  2633. int ray_number;
  2634. {
  2635.   /* Just some shortcuts. */
  2636.  
  2637. #define FCD Frame.Camera->Direction
  2638. #define FCR Frame.Camera->Right
  2639. #define FCU Frame.Camera->Up
  2640. #define FCL Frame.Camera->Location
  2641.  
  2642.   DBL x0 = 0.0, y0 = 0.0;
  2643.   DBL cx, sx, cy, sy, ty, rad, phi, lx, ly;
  2644.   VECTOR V1;
  2645.  
  2646.   /* Create primary ray according to the camera used. */
  2647.  
  2648.   Assign_Vector(Ray->Initial, FCL);
  2649.  
  2650.   Initialize_Ray_Containers(Ray);
  2651.  
  2652.   switch (Frame.Camera->Type)
  2653.   {
  2654.     /*
  2655.      * Perspective projection (Pinhole camera; POV standard).
  2656.      */
  2657.  
  2658.     case PERSPECTIVE_CAMERA:
  2659.  
  2660.       /* Convert the x coordinate to be a DBL from -0.5 to 0.5. */
  2661.  
  2662.       x0 = x / (DBL)Frame.Screen_Width - 0.5;
  2663.  
  2664.       /* Convert the y coordinate to be a DBL from -0.5 to 0.5. */
  2665.  
  2666.       y0 = ((DBL)(Frame.Screen_Height - 1) - y) / (DBL)Frame.Screen_Height - 0.5;
  2667.  
  2668.       /* Create primary ray. */
  2669.  
  2670.       VLinComb3(Ray->Direction, 1.0, FCD, x0, FCR, y0, FCU);
  2671.  
  2672.       /* Do focal blurring (by Dan Farmer). */
  2673.  
  2674.       if (Focal_Blur_Is_Used)
  2675.       {
  2676.         jitter_camera_ray(Ray, ray_number);
  2677.  
  2678.         initialize_ray_container_state(Ray, TRUE);
  2679.       }
  2680.       else
  2681.       {
  2682.         initialize_ray_container_state(Ray, Precompute_Camera_Constants);
  2683.  
  2684.         Precompute_Camera_Constants = FALSE;
  2685.       }
  2686.  
  2687.     break;
  2688.  
  2689.     /*
  2690.      * Orthographic projection.
  2691.      */
  2692.  
  2693.     case ORTHOGRAPHIC_CAMERA:
  2694.  
  2695.       /* Convert the x coordinate to be a DBL from -0.5 to 0.5. */
  2696.  
  2697.       x0 = x / (DBL)Frame.Screen_Width - 0.5;
  2698.  
  2699.       /* Convert the y coordinate to be a DBL from -0.5 to 0.5. */
  2700.  
  2701.       y0 = ((DBL)(Frame.Screen_Height - 1) - y) / (DBL)Frame.Screen_Height - 0.5;
  2702.  
  2703.       /* Create primary ray. */
  2704.  
  2705.       Assign_Vector(Ray->Direction, FCD);
  2706.  
  2707.       VLinComb3(Ray->Initial, 1.0, FCL, x0, FCR, y0, FCU);
  2708.  
  2709.       initialize_ray_container_state(Ray, TRUE);
  2710.  
  2711.       break;
  2712.  
  2713.     /*
  2714.      * Fisheye camera.
  2715.      */
  2716.  
  2717.     case FISHEYE_CAMERA:
  2718.  
  2719.       /* Convert the x coordinate to be a DBL from -1.0 to 1.0. */
  2720.  
  2721.       x0 = 2.0 * x / (DBL)Frame.Screen_Width - 1.0;
  2722.  
  2723.       /* Convert the y coordinate to be a DBL from -1.0 to 1.0. */
  2724.  
  2725.       y0 = 2.0 * ((DBL)(Frame.Screen_Height - 1) - y) / (DBL)Frame.Screen_Height - 1.0;
  2726.  
  2727.       /* Get aspect ratio --> we want a circle (do this only once). */
  2728.  
  2729.       if (Precompute_Camera_Constants)
  2730.       {
  2731.         VLength(lx, FCR);
  2732.         VLength(ly, FCU);
  2733.  
  2734.         Camera_Aspect_Ratio = lx / ly;
  2735.  
  2736.         VNormalize(FCR, FCR);
  2737.         VNormalize(FCU, FCU);
  2738.         VNormalize(FCD, FCD);
  2739.       }
  2740.  
  2741.       /* Get polar coordinates. */
  2742.  
  2743.       x0 *= Camera_Aspect_Ratio;
  2744.  
  2745.       rad = sqrt(x0 * x0 + y0 * y0);
  2746.  
  2747.       /* If the pixel lies outside the unit circle no ray is traced. */
  2748.  
  2749.       if (rad > 1.0)
  2750.       {
  2751.         return(FALSE);
  2752.       }
  2753.  
  2754.       if (rad == 0.0)
  2755.       {
  2756.         phi = 0.0;
  2757.       }
  2758.       else
  2759.       {
  2760.         if (x0 < 0.0)
  2761.         {
  2762.           phi = M_PI - asin(y0 / rad);
  2763.         }
  2764.         else
  2765.         {
  2766.           phi = asin(y0 / rad);
  2767.         }
  2768.       }
  2769.  
  2770.       /* Get spherical coordinates. */
  2771.  
  2772.       x0 = phi;
  2773.  
  2774.       /* Set vertical angle to half viewing angle. */
  2775.  
  2776.       y0 = rad * Frame.Camera->Angle * M_PI / 360.0;
  2777.  
  2778.       /* Create primary ray. */
  2779.  
  2780.       cx = cos(x0);  sx = sin(x0);
  2781.       cy = cos(y0);  sy = sin(y0);
  2782.  
  2783.       VLinComb3(Ray->Direction, cx * sy, FCR, sx * sy, FCU, cy, FCD);
  2784.  
  2785.       initialize_ray_container_state(Ray, Precompute_Camera_Constants);
  2786.  
  2787.       Precompute_Camera_Constants = FALSE;
  2788.  
  2789.       break;
  2790.  
  2791.     /*
  2792.      * Omnimax camera.
  2793.      */
  2794.  
  2795.     case OMNIMAX_CAMERA:
  2796.  
  2797.       /* Convert the x coordinate to be a DBL from -1.0 to 1.0. */
  2798.  
  2799.       x0 = 2.0 * x / (DBL)Frame.Screen_Width - 1.0;
  2800.  
  2801.       /* Convert the y coordinate to be a DBL from -1.0 to 1.0. */
  2802.  
  2803.       y0 = 2.0 * ((DBL)(Frame.Screen_Height - 1) - y) / (DBL)Frame.Screen_Height - 1.0;
  2804.  
  2805.       /* Get aspect ratio --> we want a circle (do this only once). */
  2806.  
  2807.       if (Precompute_Camera_Constants)
  2808.       {
  2809.         VLength(lx, FCR);
  2810.         VLength(ly, FCU);
  2811.  
  2812.         Camera_Aspect_Ratio = lx / ly;
  2813.  
  2814.         VNormalize(FCR, FCR);
  2815.         VNormalize(FCU, FCU);
  2816.         VNormalize(FCD, FCD);
  2817.       }
  2818.  
  2819.       /* Get polar coordinates. */
  2820.  
  2821.       x0 *= Camera_Aspect_Ratio;
  2822.  
  2823.       rad = sqrt(x0 * x0 + y0 * y0);
  2824.  
  2825.       /* If the pixel lies outside the unit circle no ray is traced. */
  2826.  
  2827.       if (rad > 1.0)
  2828.       {
  2829.         return(FALSE);
  2830.       }
  2831.  
  2832.       if (rad == 0.0)
  2833.       {
  2834.         phi = 0.0;
  2835.       }
  2836.       else
  2837.       {
  2838.         if (x0 < 0.0)
  2839.         {
  2840.           phi = M_PI - asin(y0 / rad);
  2841.         }
  2842.         else
  2843.         {
  2844.           phi = asin(y0 / rad);
  2845.         }
  2846.       }
  2847.  
  2848.       /* Get spherical coordinates. */
  2849.  
  2850.       x0 = phi;
  2851.  
  2852.       y0 = 1.411269 * rad - 0.09439 * rad * rad * rad + 0.25674 * rad * rad * rad * rad * rad;
  2853.  
  2854.       cx = cos(x0);  sx = sin(x0);
  2855.       cy = cos(y0);  sy = sin(y0);
  2856.  
  2857.       /* We can't see below 45 degrees under the projection axis. */
  2858.  
  2859.       if (sx * sy < tan(135.0 / 180.0 * M_PI) * cy)
  2860.       {
  2861.         return(FALSE);
  2862.       }
  2863.  
  2864.       /* Create primary ray. */
  2865.  
  2866.       VLinComb3(Ray->Direction, cx * sy, FCR, sx * sy, FCU, cy, FCD);
  2867.  
  2868.       initialize_ray_container_state(Ray, Precompute_Camera_Constants);
  2869.  
  2870.       Precompute_Camera_Constants = FALSE;
  2871.  
  2872.       break;
  2873.  
  2874.     /*
  2875.      * Panoramic camera from Graphic Gems III.
  2876.      */
  2877.  
  2878.     case PANORAMIC_CAMERA:
  2879.  
  2880.       /* Convert the x coordinate to be a DBL from 0.0 to 1.0. */
  2881.  
  2882.       x0 = x / (DBL)Frame.Screen_Width;
  2883.  
  2884.       /* Convert the y coordinate to be a DBL from -1.0 to 1.0. */
  2885.  
  2886.       y0 = 2.0 * ((DBL)(Frame.Screen_Height - 1) - y) / (DBL)Frame.Screen_Height - 1.0;
  2887.  
  2888.       /* Get cylindrical coordinates. */
  2889.  
  2890.       x0 = (1.0 - x0) * M_PI;
  2891.  
  2892.       y0 = 0.5 * M_PI * y0;
  2893.  
  2894.       cx = cos(x0);
  2895.       sx = sin(x0);
  2896.  
  2897.       if (fabs(0.5 * M_PI - fabs(y0)) < EPSILON)
  2898.       {
  2899.         if (y0 > 0.0)
  2900.         {
  2901.           ty = BOUND_HUGE;
  2902.         }
  2903.         else
  2904.         {
  2905.           ty = - BOUND_HUGE;
  2906.         }
  2907.       }
  2908.       else
  2909.       {
  2910.         ty = tan(y0);
  2911.       }
  2912.  
  2913.       /* Create primary ray. */
  2914.  
  2915.       VLinComb3(Ray->Direction, cx, FCR, ty, FCU, sx, FCD);
  2916.  
  2917.       initialize_ray_container_state(Ray, Precompute_Camera_Constants);
  2918.  
  2919.       Precompute_Camera_Constants = FALSE;
  2920.  
  2921.       break;
  2922.  
  2923.     /*
  2924.      * Ultra wide angle camera written by Dan Farmer.
  2925.      */
  2926.  
  2927.     case ULTRA_WIDE_ANGLE_CAMERA:
  2928.  
  2929.       /* Convert the x coordinate to be a DBL from -0.5 to 0.5. */
  2930.  
  2931.       x0 = x / (DBL)Frame.Screen_Width - 0.5;
  2932.  
  2933.       /* Convert the y coordinate to be a DBL from -0.5 to 0.5. */
  2934.  
  2935.       y0 = ((DBL)(Frame.Screen_Height - 1) - y) / (DBL)Frame.Screen_Height - 0.5;
  2936.  
  2937.       /* Create primary ray. */
  2938.  
  2939.       x0 *= Frame.Camera->Angle / 180.0;
  2940.  
  2941.       y0 *= Frame.Camera->Angle / 180.0;
  2942.  
  2943.       cx = cos(x0);  sx = sin(x0);
  2944.       cy = cos(y0);  sy = sin(y0);
  2945.  
  2946.       VLinComb3(Ray->Direction, sx, FCR, sy, FCU, cx * cy, FCD);
  2947.  
  2948.       initialize_ray_container_state(Ray, Precompute_Camera_Constants);
  2949.  
  2950.       Precompute_Camera_Constants = FALSE;
  2951.  
  2952.       break;
  2953.  
  2954.     /*
  2955.      * Cylinder camera 1. Axis in "up" direction
  2956.      */
  2957.  
  2958.     case CYL_1_CAMERA:
  2959.  
  2960.       /* Convert the x coordinate to be a DBL from -0.5 to 0.5. */
  2961.  
  2962.       x0 = x / (DBL)Frame.Screen_Width - 0.5;
  2963.  
  2964.       /* Convert the y coordinate to be a DBL from -0.5 to 0.5. */
  2965.  
  2966.       y0 = ((DBL)(Frame.Screen_Height - 1) - y) / (DBL)Frame.Screen_Height - 0.5;
  2967.  
  2968.       /* Create primary ray. */
  2969.  
  2970.       x0 *= Frame.Camera->Angle * M_PI / 180.0;
  2971.  
  2972.       cx = cos(x0);
  2973.       sx = sin(x0);
  2974.  
  2975.       VLinComb3(Ray->Direction, sx, FCR, y0, FCU, cx, FCD);
  2976.  
  2977.       initialize_ray_container_state(Ray, Precompute_Camera_Constants);
  2978.  
  2979.       Precompute_Camera_Constants = FALSE;
  2980.  
  2981.       break;
  2982.  
  2983.     /*
  2984.      * Cylinder camera 2. Axis in "right" direction
  2985.      */
  2986.  
  2987.     case CYL_2_CAMERA:
  2988.  
  2989.       /* Convert the x coordinate to be a DBL from -0.5 to 0.5. */
  2990.  
  2991.       x0 = x / (DBL)Frame.Screen_Width - 0.5;
  2992.  
  2993.       /* Convert the y coordinate to be a DBL from -0.5 to 0.5. */
  2994.  
  2995.       y0 = ((DBL)(Frame.Screen_Height - 1) - y) / (DBL)Frame.Screen_Height - 0.5;
  2996.  
  2997.       /* Create primary ray. */
  2998.  
  2999.       y0 *= Frame.Camera->Angle * M_PI / 180.0;
  3000.  
  3001.       cy = cos(y0);
  3002.       sy = sin(y0);
  3003.  
  3004.       VLinComb3(Ray->Direction, x0, FCR, sy, FCU, cy, FCD);
  3005.  
  3006.       initialize_ray_container_state(Ray, Precompute_Camera_Constants);
  3007.  
  3008.       Precompute_Camera_Constants = FALSE;
  3009.  
  3010.       break;
  3011.  
  3012.     /*
  3013.      * Cylinder camera 3. Axis in "up" direction, orthogonal in "right"
  3014.      */
  3015.  
  3016.     case CYL_3_CAMERA:
  3017.  
  3018.       /* Convert the x coordinate to be a DBL from -0.5 to 0.5. */
  3019.  
  3020.       x0 = x / (DBL)Frame.Screen_Width - 0.5;
  3021.  
  3022.       /* Convert the y coordinate to be a DBL from -0.5 to 0.5. */
  3023.  
  3024.       y0 = ((DBL)(Frame.Screen_Height - 1) - y) / (DBL)Frame.Screen_Height - 0.5;
  3025.  
  3026.       /* Create primary ray. */
  3027.  
  3028.       x0 *= Frame.Camera->Angle * M_PI / 180.0;
  3029.  
  3030.       cx = cos(x0);
  3031.       sx = sin(x0);
  3032.  
  3033.       VLinComb2(Ray->Direction, sx, FCR, cx, FCD);
  3034.  
  3035.       VLinComb2(Ray->Initial, 1.0, FCL, y0, FCU);
  3036.  
  3037.       initialize_ray_container_state(Ray, TRUE);
  3038.  
  3039.       break;
  3040.  
  3041.     /*
  3042.      * Cylinder camera 4. Axis in "right" direction, orthogonal in "up"
  3043.      */
  3044.  
  3045.     case CYL_4_CAMERA:
  3046.  
  3047.       /* Convert the x coordinate to be a DBL from -0.5 to 0.5. */
  3048.  
  3049.       x0 = x / (DBL)Frame.Screen_Width - 0.5;
  3050.  
  3051.       /* Convert the y coordinate to be a DBL from -0.5 to 0.5. */
  3052.  
  3053.       y0 = ((DBL)(Frame.Screen_Height - 1) - y) / (DBL)Frame.Screen_Height - 0.5;
  3054.  
  3055.       /* Create primary ray. */
  3056.  
  3057.       y0 *= Frame.Camera->Angle * M_PI / 180.0;
  3058.  
  3059.       cy = cos(y0);
  3060.       sy = sin(y0);
  3061.  
  3062.       VLinComb2(Ray->Direction, sy, FCU, cy, FCD);
  3063.  
  3064.       VLinComb2(Ray->Initial, 1.0, FCL, x0, FCR);
  3065.  
  3066.       initialize_ray_container_state(Ray, TRUE);
  3067.  
  3068.       break;
  3069.  
  3070.     /*
  3071.      * Test camera 1.
  3072.      */
  3073.  
  3074.     case TEST_CAMERA_1:
  3075.  
  3076.       break;
  3077.  
  3078.     /*
  3079.      * Test camera 2.
  3080.      */
  3081.  
  3082.     case TEST_CAMERA_2:
  3083.  
  3084.       break;
  3085.  
  3086.     /*
  3087.      * Test camera 3.
  3088.      */
  3089.  
  3090.     case TEST_CAMERA_3:
  3091.  
  3092.       break;
  3093.  
  3094.     /*
  3095.      * Test camera 4.
  3096.      */
  3097.  
  3098.     case TEST_CAMERA_4:
  3099.  
  3100.       break;
  3101.  
  3102.     default:
  3103.  
  3104.     Error("Unknown camera type in create_ray().\n");
  3105.   }
  3106.  
  3107.   if (Frame.Camera->Tnormal != NULL)
  3108.   {
  3109.     VNormalize(Ray->Direction, Ray->Direction);
  3110.  
  3111.     Make_Vector(V1, x0, y0, 0.0);
  3112.     
  3113.     Perturb_Normal(Ray->Direction, Frame.Camera->Tnormal, V1);
  3114.   }
  3115.   
  3116.   VNormalize(Ray->Direction, Ray->Direction);
  3117.   
  3118.   return(TRUE);
  3119.  
  3120. #undef FCD
  3121. #undef FCR
  3122. #undef FCU
  3123. #undef FCL
  3124. }
  3125.  
  3126.  
  3127.  
  3128. /*****************************************************************************
  3129. *
  3130. * FUNCTION
  3131. *
  3132. *   gamma_correct
  3133. *
  3134. * INPUT
  3135. *
  3136. *   Colour (an array of DBL's)
  3137. *   
  3138. * OUTPUT
  3139. *
  3140. *   The colour array
  3141. *   
  3142. * RETURNS
  3143. *   
  3144. * AUTHOR
  3145. *
  3146. *   POV-Ray Team
  3147. *   
  3148. * DESCRIPTION
  3149. *
  3150. *   Adjust RGB values for overall brightness and gamma curve so that the
  3151. *   image appears a constant brightness regardless of the hardware that
  3152. *   is being used.  This can't be part of extract_colors, since
  3153. *   extract_colors is used multiple times in anti aliasing, and this has
  3154. *   to be called exactly once per pixel output.
  3155. *
  3156. *   If gamma correction is enabled, then file and display pixel values 
  3157. *   will be corrected for the current assumed_gamma, which has default
  3158. *   value 1.00, but can be set by a global_settings {assumed_gamma} in the
  3159. *   source file, and the DisplayGamma value, which can be set in the INI
  3160. *   file via Display_Gamma=n.n or defaults to DEFAULT_DISPLAY_GAMMA
  3161. *   (2.2 unless another value set in the system specific config.h files.)
  3162. *
  3163. *   If gamma correction is turned off (if no global_settings {assumed_gamma}
  3164. *   line occurrs in the scene file) then no gamma correction will be done 
  3165. *   on the pixel values.  If gamma correction is turned off, the 
  3166. *   DisplayGamma value is still relevant for PNG output files, since if 
  3167. *   gamma correction is disabled, it is presumed that the scene is 
  3168. *   "pre-corrected" for the current hardware, and a gAMA chunk with the 
  3169. *   current 1/DisplayGamma value will be output.
  3170. *
  3171. *   When DisplayGamma approximately equals assumed_gamma, it means that we
  3172. *   don't need to do any gamma correction since it is already the correct
  3173. *   brightness.  opts.GammaFactor is calculated once in tokenize.c to
  3174. *   be assumed_gamma/DisplayGamma to avoid re-calculation for each pixel.
  3175. *
  3176. * CHANGES
  3177. *
  3178. *   Apr 1995 :  Created function - Jim McElhiney
  3179. *   Oct 1995 :  Modified to do proper system gamma correction [AED]
  3180. *
  3181. ******************************************************************************/
  3182.  
  3183. static void gamma_correct(Colour)
  3184. COLOUR Colour;
  3185. {
  3186.   if (opts.Options & GAMMA_CORRECT)
  3187.   {
  3188.     Colour[RED]   = pow(Colour[RED],  opts.GammaFactor);
  3189.     Colour[GREEN] = pow(Colour[GREEN],opts.GammaFactor);
  3190.     Colour[BLUE]  = pow(Colour[BLUE], opts.GammaFactor);
  3191.   }
  3192. }
  3193.  
  3194.  
  3195.  
  3196. /*****************************************************************************
  3197. *
  3198. * FUNCTION
  3199. *
  3200. *   extract_colors
  3201. *
  3202. * INPUT
  3203. *
  3204. *   Colour, Red, Green, Blue, Alpha, grey
  3205. *   
  3206. * OUTPUT
  3207. *
  3208. *   Red, Green, Blue, Alpha, grey
  3209. *   
  3210. * RETURNS
  3211. *   
  3212. * AUTHOR
  3213. *
  3214. *   POV-Ray Team
  3215. *   
  3216. * DESCRIPTION
  3217. *
  3218. *   Create appropriate rgba values.
  3219. *
  3220. * CHANGES
  3221. *
  3222. *   Aug 1994 : Extracted common code from Start_Tracing - Eduard Schwan
  3223. *   Jun 1995 : Alpha channel support -CEY
  3224. *
  3225. ******************************************************************************/
  3226.  
  3227. static void extract_colors(Colour, Red, Green, Blue, Alpha, grey)
  3228. COLOUR Colour;
  3229. unsigned char *Red, *Green, *Blue, *Alpha;
  3230. DBL *grey;
  3231. {
  3232.   if (opts.PaletteOption == GREY)
  3233.   {
  3234.     *grey = Colour[RED] * 0.287 + Colour[GREEN] * 0.589 + Colour[BLUE] * 0.114;
  3235.  
  3236.     *Red = *Green = *Blue = (unsigned char)((*grey) * maxclr);
  3237.   }
  3238.   else
  3239.   {
  3240.     *Red   = (unsigned char)(Colour[RED]    * maxclr);
  3241.     *Green = (unsigned char)(Colour[GREEN]  * maxclr);
  3242.     *Blue  = (unsigned char)(Colour[BLUE]   * maxclr);
  3243.     *Alpha = (unsigned char)(Colour[TRANSM] * maxclr);
  3244.   }
  3245. }
  3246.  
  3247.  
  3248.  
  3249. /*****************************************************************************
  3250. *
  3251. * FUNCTION
  3252. *
  3253. *   plot_pixel
  3254. *
  3255. * INPUT
  3256. *
  3257. *   x, y   - pixel location
  3258. *   Colour - pixel color
  3259. *   
  3260. * OUTPUT
  3261. *   
  3262. * RETURNS
  3263. *   
  3264. * AUTHOR
  3265. *
  3266. *   Dieter Bayer
  3267. *
  3268. * DESCRIPTION
  3269. *
  3270. *   Display a pixel on the screen.
  3271. *
  3272. * CHANGES
  3273. *
  3274. *   Aug 1995 : Creation. Extracted from common code.
  3275. *
  3276. ******************************************************************************/
  3277.  
  3278. static void plot_pixel(x, y, Colour)
  3279. int x, y;
  3280. COLOUR Colour;
  3281. {
  3282.   unsigned char Red, Green, Blue, Alpha;
  3283.   DBL grey;
  3284.  
  3285.   if ((opts.Options & DISPLAY) && (y != opts.First_Line - 1))
  3286.   {
  3287.     extract_colors(Colour, &Red, &Green, &Blue, &Alpha, &grey);
  3288.  
  3289.     POV_DISPLAY_PLOT(x, y, Red, Green, Blue, Alpha);
  3290.   }
  3291. }
  3292.  
  3293.  
  3294.  
  3295. /*****************************************************************************
  3296. *
  3297. * FUNCTION
  3298. *
  3299. *   jitter_pixel_position
  3300. *
  3301. * INPUT
  3302. *
  3303. *   x, y     - pixel location
  3304. *   
  3305. * OUTPUT
  3306. *
  3307. *   Jitter_X - pseudo-random offset to x-coordinate
  3308. *   Jitter_Y - pseudo-random offset to y-coordinate
  3309. *   
  3310. * RETURNS
  3311. *   
  3312. * AUTHOR
  3313. *
  3314. *   Dieter Bayer
  3315. *   
  3316. * DESCRIPTION
  3317. *
  3318. *   Apply jitter to a pixel location.
  3319. *
  3320. * CHANGES
  3321. *
  3322. *   Aug 1995 : Creation. Extracted from common code.
  3323. *
  3324. ******************************************************************************/
  3325.  
  3326. static void jitter_pixel_position(x, y, Jitter_X, Jitter_Y)
  3327. int x, y;
  3328. DBL *Jitter_X, *Jitter_Y;
  3329. {
  3330.   static int Jitt_Offset = 10;
  3331.  
  3332.   if (opts.Options & JITTER)
  3333.   {
  3334.     *Jitter_X = rand2d(x + Jitt_Offset, y);
  3335.  
  3336.     Jitt_Offset++;
  3337.  
  3338.     *Jitter_Y = rand2d(x + Jitt_Offset, y);
  3339.  
  3340.     Jitt_Offset++;
  3341.  
  3342.     *Jitter_X *= JitterScale;
  3343.     *Jitter_Y *= JitterScale;
  3344.   }
  3345.   else
  3346.   {
  3347.     *Jitter_X = *Jitter_Y = 0.0;
  3348.   }
  3349. }
  3350.  
  3351. /*****************************************************************************
  3352. *
  3353. * FUNCTION
  3354. *
  3355. *   output_line
  3356. *
  3357. * INPUT
  3358. *
  3359. *   y              - current line number
  3360. *   
  3361. * OUTPUT
  3362. *   
  3363. * RETURNS
  3364. *   
  3365. * AUTHOR
  3366. *
  3367. *   POV-Ray Team
  3368. *   
  3369. * DESCRIPTION
  3370. *
  3371. *   -
  3372. *
  3373. * CHANGES
  3374. *
  3375. *   -
  3376. *
  3377. ******************************************************************************/
  3378.  
  3379. static void output_line(y)
  3380. int y;
  3381. {
  3382.   COLOUR *Temp_Colour_Ptr;
  3383.   char *Temp_Char_Ptr;
  3384.  
  3385.   if (opts.Options & DISKWRITE)
  3386.   {
  3387.     if (y > opts.First_Line)
  3388.     {
  3389.       Write_Line(Output_File_Handle, Previous_Line, y - 1);
  3390.     }
  3391.   }
  3392.  
  3393.   if (opts.Options & VERBOSE)
  3394.   {
  3395.     if (opts.Options & ANTIALIAS)
  3396.     {
  3397.       if (opts.Options & RADIOSITY)
  3398.       {
  3399.         Status_Info(" supersampled %d, %ld radiosity.",
  3400.                     SuperSampleCount, ra_gather_count - RadiosityCount);
  3401.       }
  3402.       else
  3403.       {
  3404.         Status_Info(" supersampled %d times.", SuperSampleCount);
  3405.       }
  3406.     }
  3407.     else
  3408.     {
  3409.       if (opts.Options & RADIOSITY)
  3410.       {
  3411.         Status_Info("  %ld radiosity samples.", ra_gather_count - RadiosityCount);
  3412.       }
  3413.     }
  3414.  
  3415.     Status_Info("       \r");
  3416.   }
  3417.  
  3418.   Temp_Colour_Ptr = Previous_Line;
  3419.   Previous_Line   = Current_Line;
  3420.   Current_Line    = Temp_Colour_Ptr;
  3421.  
  3422.   Temp_Char_Ptr                   = Previous_Line_Antialiased_Flags;
  3423.   Previous_Line_Antialiased_Flags = Current_Line_Antialiased_Flags;
  3424.   Current_Line_Antialiased_Flags  = Temp_Char_Ptr;
  3425. }
  3426.  
  3427. /*****************************************************************************
  3428. *
  3429. * FUNCTION
  3430. *
  3431. *   initialise_histogram
  3432. *
  3433. * INPUT
  3434. *
  3435. * OUTPUT
  3436. *
  3437. * RETURNS
  3438. *
  3439. * AUTHOR
  3440. *
  3441. *   Chris Cason
  3442. *
  3443. * DESCRIPTION
  3444. *
  3445. * Initialise histogram collation if available, otherwise force histogram off.
  3446. *
  3447. * CHANGES
  3448. *
  3449. ******************************************************************************/
  3450.  
  3451. static void initialise_histogram ()
  3452. {
  3453. #if PRECISION_TIMER_AVAILABLE
  3454.   if (opts.histogram_on)
  3455.   {
  3456.     PRECISION_TIMER_INIT
  3457.     histogram_grid = POV_CALLOC (opts.histogram_x * opts.histogram_y,
  3458.                                  sizeof(unsigned long), "histogram grid");
  3459.   }
  3460. #else
  3461.   opts.histogram_on = FALSE ;
  3462. #endif
  3463. }
  3464.  
  3465. /*****************************************************************************
  3466. *
  3467. * FUNCTION
  3468. *
  3469. *   destroy_histogram
  3470. *
  3471. * INPUT
  3472. *
  3473. * OUTPUT
  3474. *
  3475. * RETURNS
  3476. *
  3477. * AUTHOR
  3478. *
  3479. *   Andreas Dilger
  3480. *
  3481. * DESCRIPTION
  3482. *
  3483. * CHANGES
  3484. *
  3485. ******************************************************************************/
  3486.  
  3487. void destroy_histogram ()
  3488. {
  3489. #if PRECISION_TIMER_AVAILABLE
  3490.   if (Histogram_File_Handle != NULL)
  3491.   {
  3492.     Close_File(Histogram_File_Handle);
  3493.     POV_FREE(Histogram_File_Handle);
  3494.     Histogram_File_Handle = NULL;
  3495.   }
  3496.  
  3497.   if (histogram_grid != NULL)
  3498.   {
  3499.     POV_FREE (histogram_grid) ;
  3500.     histogram_grid = NULL;
  3501.   }
  3502. #endif
  3503. }
  3504.  
  3505. /*****************************************************************************
  3506. *
  3507. * FUNCTION
  3508. *
  3509. *   accumulate_histogram
  3510. *
  3511. * INPUT
  3512. *
  3513. *   int x, y - pixel position on screen, on - starting pixel
  3514. *   
  3515. * OUTPUT
  3516. *   
  3517. * RETURNS
  3518. *   
  3519. * AUTHOR
  3520. *
  3521. *   Chris Cason
  3522. *   
  3523. * DESCRIPTION
  3524. *
  3525. * Accumulate statistics on the histogram grid given on the command line.
  3526. * The total amount of time that the program spends in tracing pixels in the
  3527. * particular grid section that the pixel lies in is eventually written to an
  3528. * output file.
  3529. *
  3530. * CHANGES
  3531. *
  3532. * Oct 1995:  Modified to return if PRECISION_TIMER_AVAILABLE == 0 [CJC]
  3533. *
  3534. ******************************************************************************/
  3535.  
  3536. static void accumulate_histogram(x, y, on)
  3537. int x, y, on;
  3538. {
  3539. #if PRECISION_TIMER_AVAILABLE
  3540.   int loc_x, loc_y;
  3541.   unsigned long  *p;
  3542.  
  3543.   if (y < 0)
  3544.   {
  3545.     return;
  3546.   }
  3547.  
  3548.   if (!on)
  3549.   {
  3550.     PRECISION_TIMER_STOP
  3551.  
  3552.     /* determine which grid section the pixel lies in */
  3553.  
  3554.     loc_x = x * opts.histogram_x / Frame.Screen_Width;
  3555.     loc_y = y * opts.histogram_y / Frame.Screen_Height;
  3556.  
  3557.     p = histogram_grid + (long) loc_y * opts.histogram_x + loc_x;
  3558.  
  3559.     *p += PRECISION_TIMER_COUNT;
  3560.  
  3561.     if (*p > max_histogram_value)
  3562.     {
  3563.       max_histogram_value = *p;
  3564.     }
  3565.   }
  3566.   else
  3567.   {
  3568.     PRECISION_TIMER_START
  3569.   }
  3570. #endif
  3571. }
  3572.  
  3573. /*****************************************************************************
  3574. *
  3575. * FUNCTION
  3576. *
  3577. *   write_histogram
  3578. *
  3579. * INPUT
  3580. *
  3581. *   filename - file to output the data to.
  3582. *   
  3583. * OUTPUT
  3584. *   
  3585. * RETURNS
  3586. *   
  3587. * AUTHOR
  3588. *
  3589. *   Chris Cason
  3590. *   
  3591. * DESCRIPTION
  3592. *
  3593. * Processes and then writes the accumulated histogram statistics to a CSV
  3594. * (comma separated value) file. Programs such as Microsoft Excel can read CSV.
  3595. * Also accomodates image file output, such as Targa, for height field usage.
  3596. *
  3597. * CHANGES
  3598. *
  3599. * Sep 1995:  Added support for grayscale PNG histogram output [AED]
  3600. * Oct 1995:  Fixed TGA, PPM output for 0 - 1 range and use HF_GRAY_16 [AED]
  3601. * Oct 1995:  Modified to return if PRECISION_TIMER_AVAILABLE == 0 [CJC]
  3602. *
  3603. ******************************************************************************/
  3604.  
  3605. void write_histogram(filename)
  3606. char *filename;
  3607. {
  3608. #if PRECISION_TIMER_AVAILABLE
  3609.   int x, y, x_step, y_step;
  3610.   unsigned long OptionsSave;
  3611.   int OutputQualitySave;
  3612.   unsigned long *p;
  3613.   FILE *f;
  3614.   COLOUR *line, *l;
  3615.  
  3616.   Status_Info ("\nWriting histogram file '%s'", filename);
  3617.  
  3618.   switch (opts.histogram_type)
  3619.   {
  3620.     case CSV :
  3621.  
  3622.       if ((f = fopen (filename, WRITE_FILE_STRING)) == NULL)
  3623.       {
  3624.         Warning (0.0, "Cannot open file %s for histogram output.", filename);
  3625.  
  3626.         return;
  3627.       }
  3628.  
  3629.       for (y = 0, p = histogram_grid; y < opts.histogram_y ; y++)
  3630.       {
  3631.         for (x = 0; x < opts.histogram_x ; x++)
  3632.         {
  3633.              fprintf (f, "%s%010lu", x ? ", " : "", *p++);
  3634.         }
  3635.  
  3636.         fprintf (f, "\n");
  3637.       }
  3638.  
  3639.       fclose (f);
  3640.  
  3641.       break;
  3642.  
  3643.     case PPM :
  3644.     case SYS :
  3645.     case TARGA :
  3646.     case PNG:
  3647.  
  3648.       OptionsSave = opts.Options;
  3649.       OutputQualitySave = opts.OutputQuality;
  3650.  
  3651.       opts.Options = HF_GRAY_16;
  3652.       opts.OutputQuality = 12;
  3653.  
  3654.       Histogram_File_Handle->file_type = HIST_FTYPE;
  3655.  
  3656.       if (Open_File (Histogram_File_Handle, filename,
  3657.           &Frame.Screen_Width, &Frame.Screen_Height, 0, WRITE_MODE) != 1)
  3658.       {
  3659.         Warning (0.0, "Cannot open file %s for histogram output.", filename);
  3660.         return;
  3661.       }
  3662.  
  3663.       line = (COLOUR *)POV_CALLOC(Frame.Screen_Width, sizeof(COLOUR), "histogram buffer");
  3664.  
  3665.       y_step = Frame.Screen_Height / opts.histogram_y;
  3666.       x_step = Frame.Screen_Width / opts.histogram_x;
  3667.  
  3668.       for (y = 0; y < Frame.Screen_Height ; y++)
  3669.       {
  3670.         p = histogram_grid + (long) (y / y_step) * opts.histogram_x;
  3671.  
  3672.         for (x = 0, l = line; x < Frame.Screen_Width ; x++, l++)
  3673.         {
  3674.           (*l) [RED] =
  3675.           (*l) [GREEN] =
  3676.           (*l) [BLUE] = (COLC)*(p + x / x_step) / max_histogram_value;
  3677.         }
  3678.         Write_Line (Histogram_File_Handle, line, y);
  3679.       }
  3680.  
  3681.       POV_FREE (line);
  3682.  
  3683.       Close_File (Histogram_File_Handle);
  3684.  
  3685.       POV_FREE (Histogram_File_Handle);
  3686.  
  3687.       Histogram_File_Handle=NULL;
  3688.  
  3689.       opts.Options = OptionsSave;
  3690.       opts.OutputQuality = OutputQualitySave;
  3691.  
  3692.       break;
  3693.  
  3694.     case NONE:  /* Just to quiet warnings */
  3695.     default:
  3696.       break;
  3697.   }
  3698. #endif
  3699. }
  3700.  
  3701. /*****************************************************************************
  3702. *
  3703. * FUNCTION
  3704. *
  3705. *   check_stats
  3706. *
  3707. * INPUT
  3708. *   y = current row
  3709. *   doingMosaic = 1 if doing mosaic preview (show pixWidth)
  3710. *   pixWidth = size of pixel
  3711. * OUTPUT
  3712. *
  3713. * RETURNS
  3714. *
  3715. * AUTHOR
  3716. *
  3717. *   POV-Ray Team
  3718. *
  3719. * DESCRIPTION
  3720. *
  3721. *   -
  3722. *
  3723. * CHANGES
  3724. *
  3725. *   6/17/95 esp Added display of mosaic pixWidth
  3726. *
  3727. ******************************************************************************/
  3728.  
  3729. static void check_stats(y, doingMosaic, pixWidth)
  3730. register int y;
  3731. register int doingMosaic;
  3732. register int pixWidth;
  3733. {
  3734.   DBL time_dif;
  3735.   unsigned long hrs, mins;
  3736.   DBL secs;
  3737.  
  3738.   /* New verbose options CdW */
  3739.  
  3740.   if (opts.Options & VERBOSE)
  3741.   {
  3742.     STOP_TIME
  3743.  
  3744.     time_dif = TIME_ELAPSED
  3745.     time_dif /= 200.0;
  3746.  
  3747.     if (time_dif > 0.0)
  3748.     {
  3749.       SPLIT_TIME(time_dif, &hrs, &mins, &secs);
  3750.  
  3751.       Status_Info("%3ld:%02ld:%02ld ", hrs, mins, (long)secs);
  3752.     }
  3753.     else
  3754.     {
  3755.       Status_Info("  -:--:-- ");
  3756.     }
  3757.  
  3758.     Status_Info("Rendering line %4d of %4d", y-opts.First_Line+1, opts.Last_Line-opts.First_Line);
  3759.  
  3760.     if (doingMosaic)
  3761.     {
  3762.       Status_Info(" at %dx%d  \b\b", pixWidth, pixWidth);
  3763.     }
  3764.  
  3765.     if (opts.Options & ANTIALIAS)
  3766.     {
  3767.       SuperSampleCount = 0;
  3768.     }
  3769.     else
  3770.     {
  3771.       Status_Info(". ");
  3772.     }
  3773.  
  3774.     RadiosityCount = ra_gather_count;
  3775.   }
  3776. }
  3777.  
  3778.  
  3779. /*****************************************************************************
  3780. *
  3781. * FUNCTION
  3782. *
  3783. *   initialize_ray_container_state
  3784. *
  3785. * INPUT
  3786. *
  3787. * OUTPUT
  3788. *
  3789. * RETURNS
  3790. *
  3791. * AUTHOR
  3792. *
  3793. *   Dieter Bayer
  3794. *
  3795. * DESCRIPTION
  3796. *
  3797. *   Initialize the containing lists of a primary ray by testing wether
  3798. *   the ray's starting point is inside any object. All objects that the
  3799. *   ray's origin is currently inside will be added to the containing
  3800. *   lists.
  3801. *
  3802. *   This is neccessary to make halos work if the camera is inside the
  3803. *   halo. It is also neccessary to make refraction work correctly if
  3804. *   the camera is inside this object.
  3805. *
  3806. * CHANGES
  3807. *
  3808. *   Mar 1996 : Creation.
  3809. *
  3810. ******************************************************************************/
  3811.  
  3812. static void initialize_ray_container_state(Ray, Compute)
  3813. RAY *Ray;
  3814. int Compute;
  3815. {
  3816.   int i, solid;
  3817.   OBJECT *Object;
  3818.  
  3819.   if (Compute)
  3820.   {
  3821.     Containing_Index = -1;
  3822.  
  3823.     if (!opts.Use_Slabs)
  3824.     {
  3825.       for (Object = Frame.Objects; Object != NULL; Object = Object -> Sibling)
  3826.       {
  3827.         if (Inside(Ray->Initial, Object))
  3828.         {
  3829.           Containing_Objects[++Containing_Index] = Object;
  3830.           Containing_Textures[Containing_Index]  = Object->Texture;
  3831.  
  3832.           if ((Object->Texture != NULL) &&
  3833.               (Object->Texture->Type == PLAIN_PATTERN) &&
  3834.               (Object->Texture->Finish != NULL))
  3835.           {
  3836.             Containing_IORs[Containing_Index] = Object->Texture->Finish->Index_Of_Refraction;
  3837.           }
  3838.           else
  3839.           {
  3840.             Containing_IORs[Containing_Index] = Frame.Atmosphere_IOR;
  3841.           }
  3842.         }
  3843.       }
  3844.     }
  3845.     else
  3846.     {
  3847.       initialize_ray_container_state_tree(Ray, Root_Object);
  3848.     }
  3849.   }
  3850.  
  3851.   for (i = 0; i <= Containing_Index; i++)
  3852.   {
  3853.     Ray->Containing_Textures[i] = Containing_Textures[i];
  3854.     Ray->Containing_Objects[i]  = Containing_Objects[i];
  3855.     Ray->Containing_IORs[i]     = Containing_IORs[i];
  3856.   }
  3857.  
  3858.   Ray->Containing_Index = Containing_Index;
  3859.  
  3860.   /* Test if we are in a hollow object (do this only once). */
  3861.  
  3862.   if (!Primary_Ray_State_Tested)
  3863.   {
  3864.     solid = FALSE;
  3865.  
  3866.     for (i = 0; i <= Containing_Index; i++)
  3867.     {
  3868.       if (!Test_Flag(Containing_Objects[i], HOLLOW_FLAG))
  3869.       {
  3870.         solid = TRUE;
  3871.  
  3872.         break;
  3873.       }
  3874.     }
  3875.  
  3876.     if (solid)
  3877.     {
  3878.       Warning(0.0, "Camera is inside a non-hollow object.\nAtmosphere, fog, and halo may not work as expected.\n");
  3879.     }
  3880.  
  3881.     Primary_Ray_State_Tested = TRUE;
  3882.   }
  3883. }
  3884.  
  3885.  
  3886.  
  3887. /*****************************************************************************
  3888. *
  3889. * FUNCTION
  3890. *
  3891. *   initialize_ray_container_state_tree
  3892. *
  3893. * INPUT
  3894. *
  3895. * OUTPUT
  3896. *
  3897. * RETURNS
  3898. *
  3899. * AUTHOR
  3900. *
  3901. *   Dieter Bayer
  3902. *
  3903. * DESCRIPTION
  3904. *
  3905. *   Step down the bounding box hierarchy and test for all node wether
  3906. *   the ray's origin is inside or not. If it's inside a node descend
  3907. *   further. If a leaf is reached and the ray's origin is inside the
  3908. *   leaf object insert the objects data into the ray's containing lists.
  3909. *
  3910. * CHANGES
  3911. *
  3912. *   Mar 1996 : Creation.
  3913. *
  3914. ******************************************************************************/
  3915.  
  3916. static void initialize_ray_container_state_tree(Ray, Node)
  3917. RAY *Ray;
  3918. BBOX_TREE *Node;
  3919. {
  3920.   int i;
  3921.   OBJECT *Object;
  3922.  
  3923.   /* Check current node. */
  3924.  
  3925.   if ((Ray->Initial[X] < (DBL)Node->BBox.Lower_Left[X]) ||
  3926.       (Ray->Initial[Y] < (DBL)Node->BBox.Lower_Left[Y]) ||
  3927.       (Ray->Initial[Z] < (DBL)Node->BBox.Lower_Left[Z]) ||
  3928.       (Ray->Initial[X] > (DBL)Node->BBox.Lower_Left[X] + (DBL)Node->BBox.Lengths[X]) ||
  3929.       (Ray->Initial[Y] > (DBL)Node->BBox.Lower_Left[Y] + (DBL)Node->BBox.Lengths[Y]) ||
  3930.       (Ray->Initial[Z] > (DBL)Node->BBox.Lower_Left[Z] + (DBL)Node->BBox.Lengths[Z]))
  3931.   {
  3932.     return;
  3933.   }
  3934.  
  3935.   if (Node->Entries)
  3936.   {
  3937.     /* This is a node containing leaves to be checked. */
  3938.  
  3939.     for (i = 0; i < Node->Entries; i++)
  3940.     {
  3941.       initialize_ray_container_state_tree(Ray, Node->Node[i]);
  3942.     }
  3943.   }
  3944.   else
  3945.   {
  3946.     /* This is a leaf so test contained object. */
  3947.  
  3948.     Object = (OBJECT *)Node->Node;
  3949.  
  3950.     if (Inside(Ray->Initial, Object))
  3951.     {
  3952.       if (Object->Texture != NULL)
  3953.       {
  3954.         Containing_Objects[++Containing_Index] = Object;
  3955.         Containing_Textures[Containing_Index]  = Object->Texture;
  3956.  
  3957.         if ((Object->Texture != NULL) &&
  3958.             (Object->Texture->Type == PLAIN_PATTERN) &&
  3959.             (Object->Texture->Finish != NULL))
  3960.         {
  3961.           Containing_IORs[Containing_Index] = Object->Texture->Finish->Index_Of_Refraction;
  3962.         }
  3963.         else
  3964.         {
  3965.           Containing_IORs[Containing_Index] = Frame.Atmosphere_IOR;
  3966.         }
  3967.       }
  3968.     }
  3969.   }
  3970. }
  3971.  
  3972.